โ† Back to Index

OpenShift Serverless Adoption Guide

Executive Summary

ๅฎขๆˆท็›ฎๅ‰ๅœจ AWS ไธŠ่ฟ่กŒๅคง้‡ Lambda ๅ‡ฝๆ•ฐ๏ผŒๆฏไธชไบ‘ๅŽ‚ๅ•†้ƒฝ้œ€่ฆๅ•็‹ฌ็š„ CI/CD ๆต็จ‹ใ€‚่ฟ™ๅธฆๆฅไบ†ๅทจๅคง็š„่ฟ็ปดๅผ€้”€ๅ’ŒๅŽ‚ๅ•†้”ๅฎš้ฃŽ้™ฉใ€‚้€š่ฟ‡้‡‡็”จ Red Hat OpenShift Serverless๏ผˆๅŸบไบŽ Knative๏ผ‰๏ผŒๅฎขๆˆทๅฏไปฅๅฐ†ๆ‰€ๆœ‰ serverless ๅทฅไฝœ่ดŸ่ฝฝ็ปŸไธ€ๅˆฐไธ€ไธชๅนณๅฐ๏ผŒไฝฟ็”จไธ€ๅฅ— CI/CD ๆต็จ‹๏ผŒๅฏ็งปๆคๅœฐ้ƒจ็ฝฒๅˆฐ AWS๏ผˆROSA๏ผ‰ใ€Azure๏ผˆARO๏ผ‰ใ€้˜ฟ้‡Œไบ‘ๅ’Œ GCP โ€”โ€” ๅŒๆ—ถๅˆฉ็”จ scale-to-zero ๅ’Œไธ“็”จๆœบๅ™จๆฑ ๆฅๆœ€ๅคงๅŒ–ๆˆๆœฌ่Š‚็บฆใ€‚

ๅฎžๆต‹้ชŒ่ฏๆ‘˜่ฆ

ๆœฌๆ–นๆกˆๅทฒๅœจ ROSA HCP 4.20.21 ้›†็พคไธŠๅฎŒๆˆ็ซฏๅˆฐ็ซฏ้ชŒ่ฏ๏ผŒไธŽ AWS Lambda ่ฟ›่กŒไบ†็›ดๆŽฅๅฏนๆฏ”ๆต‹่ฏ•๏ผš

ๆŒ‡ๆ ‡ AWS Lambda OpenShift Serverless (Knative)
ๅ†ทๅฏๅŠจๅปถ่ฟŸ ~292ms ~1.67s
็ƒญ่ฏทๆฑ‚ๅปถ่ฟŸ ~44-55ms ~28-30ms
Scale-to-Zero ่‡ชๅŠจ๏ผˆ~15min๏ผ‰ ่‡ชๅŠจ๏ผˆ~90s๏ผŒๅฏ้…็ฝฎ๏ผ‰
้ƒจ็ฝฒๅคๆ‚ๅบฆ 11 ไธช CLI ๅ‘ฝไปค๏ผŒ3 ไธช AWS ๆœๅŠก 1 ไธช oc apply ๅ‘ฝไปค
ๅคšไบ‘ๆ”ฏๆŒ ไป… AWS ROSA / ARO / OCP๏ผˆไปปๆ„ไบ‘๏ผ‰
CI/CD ็ฎก้“ ๆฏไธชไบ‘ๅ•็‹ฌ็ปดๆŠค ไธ€ๅฅ—็ฎก้“้€‚้…ๆ‰€ๆœ‰้›†็พค

ๆญคๅค–๏ผŒ้’ˆๅฏนๅฎขๆˆท็‰นๅˆซๅ…ณๆณจ็š„ ๅทฅไฝœๆต็ผ–ๆŽ’ ่ƒฝๅŠ›๏ผŒๆˆ‘ไปฌ่ฟ˜ๅฏนๆฏ”ไบ† SonataFlow (Serverless Logic) ๅ’Œ AWS Step Functions๏ผš

ๆŒ‡ๆ ‡ AWS Step Functions SonataFlow on ROSA
ๅทฅไฝœๆตๆ‰ง่กŒๅปถ่ฟŸ ~2ms (Express) ~46ms (็ƒญ่ฏทๆฑ‚)
้ฆ–ๆฌก่ฏทๆฑ‚ ~962ms (ๅซ CLI ๅผ€้”€) ~220ms
ๅทฅไฝœๆต่ง„่Œƒ ASL (AWS ไธ“ๆœ‰) CNCF Serverless Workflow (ๅผ€ๆ”พๆ ‡ๅ‡†)
ๅคšไบ‘ๅฏ็งปๆค โŒ ไป… AWS โœ… ไปปไฝ• OCP ้›†็พค
K8s ๅŽŸ็”Ÿ โŒ โœ… CRD + Operator

่ฏฆ็ป†ๆต‹่ฏ•ๆญฅ้ชคๅ’ŒๅฎŒๆ•ดๅ‘ฝไปค่พ“ๅ‡บ่ง steps.md


1. ๆžถๆž„ๆฆ‚่งˆ

1.1 ๅฝ“ๅ‰็Šถๆ€ vs.ย ็›ฎๆ ‡็Šถๆ€

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
        โ”‚                          ๅฝ“ๅ‰็Šถๆ€                                           โ”‚
        โ”‚                                                                             โ”‚
        โ”‚   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                          โ”‚
        โ”‚   โ”‚ AWS      โ”‚    โ”‚ CI/CD for    โ”‚   โ† ๆฏไธชไบ‘ๅ•็‹ฌ็š„ CI/CD ็ฎก้“               โ”‚
        โ”‚   โ”‚ Lambda   โ”‚โ—„โ”€โ”€โ”€โ”‚ AWS Lambda   โ”‚   โ† AWS ไธ“ๅฑž SDK, ่งฆๅ‘ๅ™จ, IAM            โ”‚
        โ”‚   โ”‚ (ๅคšไธช)   โ”‚    โ”‚ (SAM/CDK)    โ”‚                                          โ”‚
        โ”‚   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                          โ”‚
        โ”‚                                                                             โ”‚
        โ”‚   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                          โ”‚
        โ”‚   โ”‚ Azure    โ”‚    โ”‚ CI/CD for    โ”‚   โ† ๅฆไธ€ๅฅ—ๅ•็‹ฌ็š„็ฎก้“                      โ”‚
        โ”‚   โ”‚ Functionsโ”‚โ—„โ”€โ”€โ”€โ”‚ Azure Func   โ”‚   โ† Azure ไธ“ๅฑž bindings, triggers        โ”‚
        โ”‚   โ”‚ (ๆœชๆฅ)   โ”‚    โ”‚ (func CLI)   โ”‚                                          โ”‚
        โ”‚   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                          โ”‚
        โ”‚                                                                             โ”‚
        โ”‚   ้—ฎ้ข˜: N ไธชไบ‘ ร— M ไธชๅ‡ฝๆ•ฐ = Nร—M ๆก CI/CD ็ฎก้“                              โ”‚
        โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

                                      โ–ผ  ่ฟ็งป  โ–ผ

        โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
        โ”‚                          ็›ฎๆ ‡็Šถๆ€                                           โ”‚
        โ”‚                                                                             โ”‚
        โ”‚              โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                โ”‚
        โ”‚              โ”‚  ไธ€ๅฅ—็ปŸไธ€็š„ CI/CD Pipeline     โ”‚                                โ”‚
        โ”‚              โ”‚  (Tekton / OpenShift Pipelines โ”‚                               โ”‚
        โ”‚              โ”‚   + OpenShift GitOps/ArgoCD)   โ”‚                                โ”‚
        โ”‚              โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                โ”‚
        โ”‚                         โ”‚                                                    โ”‚
        โ”‚              โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                โ”‚
        โ”‚              โ”‚  ๅฎนๅ™จ้•œๅƒ (OCI)               โ”‚                                โ”‚
        โ”‚              โ”‚  + Knative Service YAML       โ”‚                                โ”‚
        โ”‚              โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                โ”‚
        โ”‚                         โ”‚                                                    โ”‚
        โ”‚         โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                            โ”‚
        โ”‚         โ–ผ               โ–ผ                       โ–ผ                            โ”‚
        โ”‚   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”           โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                        โ”‚
        โ”‚   โ”‚  ROSA    โ”‚    โ”‚  ARO     โ”‚           โ”‚  OCP on  โ”‚                        โ”‚
        โ”‚   โ”‚  (AWS)   โ”‚    โ”‚  (Azure) โ”‚           โ”‚  Ali/GCP โ”‚                        โ”‚
        โ”‚   โ”‚ Knative  โ”‚    โ”‚ Knative  โ”‚           โ”‚ Knative  โ”‚                        โ”‚
        โ”‚   โ”‚ Serving  โ”‚    โ”‚ Serving  โ”‚           โ”‚ Serving  โ”‚                        โ”‚
        โ”‚   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜           โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                        โ”‚
        โ”‚                                                                             โ”‚
        โ”‚   ็ป“ๆžœ: 1 ๆก็ฎก้“ ร— M ไธชๅ‡ฝๆ•ฐ = M ๆก CI/CD ็ฎก้“๏ผˆไบ‘ๆ— ๅ…ณ๏ผ‰                      โ”‚
        โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

1.2 ่ฏฆ็ป†็ป„ไปถๆžถๆž„

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
        โ”‚                    OpenShift ้›†็พค (ROSA / ARO / OCP)                             โ”‚
        โ”‚                                                                                 โ”‚
        โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚
        โ”‚  โ”‚                     ๆŽงๅˆถ้ข (Hosted CP / Master Nodes)                      โ”‚ โ”‚
        โ”‚  โ”‚   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                     โ”‚ โ”‚
        โ”‚  โ”‚   โ”‚ API Server   โ”‚  โ”‚ etcd         โ”‚  โ”‚ Controllers  โ”‚                     โ”‚ โ”‚
        โ”‚  โ”‚   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                     โ”‚ โ”‚
        โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚
        โ”‚                                                                                 โ”‚
        โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚
        โ”‚  โ”‚              Serverless ๅŸบ็ก€็ป„ไปถ (่ฟ่กŒๅœจ Worker / Infra ่Š‚็‚น)              โ”‚ โ”‚
        โ”‚  โ”‚   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚ โ”‚
        โ”‚  โ”‚   โ”‚ Knative Serving โ”‚  โ”‚ Knative Eventing     โ”‚  โ”‚ Kourier Ingress      โ”‚  โ”‚ โ”‚
        โ”‚  โ”‚   โ”‚ Controller      โ”‚  โ”‚ Controller           โ”‚  โ”‚ Gateway              โ”‚  โ”‚ โ”‚
        โ”‚  โ”‚   โ”‚ Activator       โ”‚  โ”‚ PingSource Adapter   โ”‚  โ”‚ (่‡ชๅŠจ TLS ่ทฏ็”ฑ)      โ”‚  โ”‚ โ”‚
        โ”‚  โ”‚   โ”‚ Autoscaler      โ”‚  โ”‚ IMC Controller       โ”‚  โ”‚                      โ”‚  โ”‚ โ”‚
        โ”‚  โ”‚   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚ โ”‚
        โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚
        โ”‚                                                                                 โ”‚
        โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚
        โ”‚  โ”‚         ไธ“็”จ Serverless ๆœบๅ™จๆฑ  (่‡ชๅŠจๆ‰ฉ็ผฉ 0 โ†’ N)                           โ”‚ โ”‚
        โ”‚  โ”‚                                                                             โ”‚ โ”‚
        โ”‚  โ”‚   Node Taint: serverless=true:NoSchedule                                    โ”‚ โ”‚
        โ”‚  โ”‚   Node Label: node-role.kubernetes.io/serverless=""                          โ”‚ โ”‚
        โ”‚  โ”‚                                                                             โ”‚ โ”‚
        โ”‚  โ”‚   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”         โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                 โ”‚ โ”‚
        โ”‚  โ”‚   โ”‚ Knative โ”‚ โ”‚ Knative โ”‚ โ”‚ Knative โ”‚  . . .  โ”‚ Knative โ”‚                 โ”‚ โ”‚
        โ”‚  โ”‚   โ”‚Service Aโ”‚ โ”‚Service Bโ”‚ โ”‚Service Cโ”‚         โ”‚Service Nโ”‚                 โ”‚ โ”‚
        โ”‚  โ”‚   โ”‚(pods)   โ”‚ โ”‚(pods)   โ”‚ โ”‚(pods)   โ”‚         โ”‚(pods)   โ”‚                 โ”‚ โ”‚
        โ”‚  โ”‚   โ”‚ scale   โ”‚ โ”‚ scale   โ”‚ โ”‚ scale   โ”‚         โ”‚ scale   โ”‚                 โ”‚ โ”‚
        โ”‚  โ”‚   โ”‚ 1โ†’100   โ”‚ โ”‚ 0โ†’50   โ”‚ โ”‚ to zero โ”‚         โ”‚ to zero โ”‚                 โ”‚ โ”‚
        โ”‚  โ”‚   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜         โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                 โ”‚ โ”‚
        โ”‚  โ”‚                                                                             โ”‚ โ”‚
        โ”‚  โ”‚   ๆ‰€ๆœ‰ pod ็ผฉ้›ถ โ†’ ้›†็พค่‡ชๅŠจ็ผฉๅฎน็งป้™ค่Š‚็‚น โ†’ ่ฎก็ฎ—ๆˆๆœฌ $0                       โ”‚ โ”‚
        โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚
        โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

2. ๅฎžๆ–ฝๆญฅ้ชค

Phase 1: ๅฎ‰่ฃ… OpenShift Serverless๏ผˆ็ฌฌ 1-2 ๅ‘จ๏ผ‰

Step 1.1: ๅฎ‰่ฃ… OpenShift Serverless Operator


        # ๅˆ›ๅปบ Operator ๆ‰€้œ€็š„ namespaceใ€OperatorGroup ๅ’Œ Subscription
        
        cat <<EOF | oc apply -f -
        apiVersion: v1
        kind: Namespace
        metadata:
          name: openshift-serverless
        ---
        apiVersion: operators.coreos.com/v1
        kind: OperatorGroup
        metadata:
          name: serverless-operators
          namespace: openshift-serverless
        spec: {}
        ---
        apiVersion: operators.coreos.com/v1alpha1
        kind: Subscription
        metadata:
          name: serverless-operator
          namespace: openshift-serverless
        spec:
          channel: stable
          installPlanApproval: Automatic
          name: serverless-operator
          source: redhat-operators
          sourceNamespace: openshift-marketplace
        EOF
        
        # ้ชŒ่ฏ Operator ๅฎ‰่ฃ…ๅฎŒๆˆ๏ผˆ็บฆ 60 ็ง’๏ผ‰
        
        oc get csv -n openshift-serverless
        
        # ้ข„ๆœŸ่พ“ๅ‡บ: serverless-operator.v1.37.1 ... Succeeded

ๅฎžๆต‹็ป“ๆžœ: Serverless Operator v1.37.1 ๅœจ็บฆ 60 ็ง’ๅ†…ๅฎ‰่ฃ…ๆˆๅŠŸใ€‚

ๅฎ˜ๆ–นๆ–‡ๆกฃ: ๅฎ‰่ฃ… OpenShift Serverless

Step 1.2: ๅฎ‰่ฃ… Knative Serving

cat <<EOF | oc apply -f -
        apiVersion: operator.knative.dev/v1beta1
        kind: KnativeServing
        metadata:
          name: knative-serving
          namespace: knative-serving
        spec:
          ingress:
            kourier:
              enabled: true
          config:
            network:
              ingress-class: kourier.ingress.networking.knative.dev
            autoscaler:
              enable-scale-to-zero: "true"
              scale-to-zero-grace-period: "30s"
              stable-window: "60s"
            defaults:
              revision-timeout-seconds: "300"
        EOF
        
        # ็ญ‰ๅพ…ๅฐฑ็ปช๏ผˆ็บฆ 50 ็ง’๏ผ‰
        
        oc wait --for=condition=Ready knativeserving/knative-serving \
          -n knative-serving --timeout=300s

ๅฎžๆต‹็ป“ๆžœ: KnativeServing (Knative 1.17) ๅœจ็บฆ 50 ็ง’ๅ†…ๅฐฑ็ปช๏ผŒ่‡ชๅŠจ้ƒจ็ฝฒไบ† activatorใ€autoscalerใ€controllerใ€webhook ๅ’Œ Kourier ingress gatewayใ€‚

ๅฎ˜ๆ–นๆ–‡ๆกฃ: Knative Serving ้…็ฝฎ

Step 1.3: ๅฎ‰่ฃ… Knative Eventing

cat <<EOF | oc apply -f -
        apiVersion: operator.knative.dev/v1beta1
        kind: KnativeEventing
        metadata:
          name: knative-eventing
          namespace: knative-eventing
        spec:
          config:
            default-ch-webhook:
              default-ch-config: |
                clusterDefault:
                  apiVersion: messaging.knative.dev/v1
                  kind: InMemoryChannel
        EOF
        
        # ็ญ‰ๅพ…ๅฐฑ็ปช๏ผˆ็บฆ 90 ็ง’๏ผ‰
        
        oc wait --for=condition=Ready knativeeventing/knative-eventing \
          -n knative-eventing --timeout=300s

ๅฎžๆต‹็ป“ๆžœ: KnativeEventing (1.17) ๅœจ็บฆ 90 ็ง’ๅ†…ๅฐฑ็ปชใ€‚

ๅฎ˜ๆ–นๆ–‡ๆกฃ: Knative Eventing ้…็ฝฎ


Phase 2: ไธ“็”จ Serverless ๆœบๅ™จๆฑ ๏ผˆ็ฌฌ 2-3 ๅ‘จ๏ผ‰

Step 2.1: ๅœจ ROSA ไธŠๅˆ›ๅปบไธ“็”จๆœบๅ™จๆฑ 


        # ๅˆ›ๅปบๆ”ฏๆŒ่‡ชๅŠจๆ‰ฉ็ผฉๅ’Œ Spot ๅฎžไพ‹็š„ไธ“็”จๆœบๅ™จๆฑ 
        
        rosa create machinepool \
          --cluster=<cluster-name> \
          --name=serverless-pool \
          --instance-type=m6a.xlarge \
          --min-replicas=0 \
          --max-replicas=10 \
          --enable-autoscaling \
          --labels="node-role.kubernetes.io/serverless=" \
          --taints="serverless=true:NoSchedule" \
          --use-spot-instances \
          --spot-max-price=on-demand
        
        # ้ชŒ่ฏๆœบๅ™จๆฑ 
        
        rosa list machinepools --cluster=<cluster-name>

ๆ ธๅฟƒๆˆๆœฌ่Š‚็บฆ็‰นๆ€ง:

Step 2.2: ๆˆๆœฌ่Š‚็บฆๆต็จ‹

  ๆ— ๆต้‡                                               ๆต้‡ๅˆฐ่พพ
          โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€                                            โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€

          โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
          โ”‚ ่ฏทๆฑ‚     โ”‚     โ”‚ Knative      โ”‚     โ”‚ ๆœบๅ™จๆฑ        โ”‚
          โ”‚ ้€Ÿ็އ = 0 โ”‚โ”€โ”€โ”€โ”€โ–ถโ”‚ Scale-to-Zeroโ”‚โ”€โ”€โ”€โ”€โ–ถโ”‚ ่Š‚็‚น = 0     โ”‚โ”€โ”€โ”€โ”€ ๆˆๆœฌ = $0
          โ”‚          โ”‚     โ”‚ Pods = 0     โ”‚     โ”‚ (่‡ชๅŠจ็ผฉๅฎน)   โ”‚
          โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

          โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
          โ”‚ ่ฏทๆฑ‚     โ”‚     โ”‚ Activator    โ”‚     โ”‚ ้›†็พค         โ”‚     โ”‚ Knative  โ”‚
          โ”‚ ๅˆฐ่พพ     โ”‚โ”€โ”€โ”€โ”€โ–ถโ”‚ ็ผ“ๅ†ฒ่ฏทๆฑ‚     โ”‚โ”€โ”€โ”€โ”€โ–ถโ”‚ ่‡ชๅŠจๆ‰ฉๅฎน     โ”‚โ”€โ”€โ”€โ”€โ–ถโ”‚ Pod      โ”‚
          โ”‚          โ”‚     โ”‚              โ”‚     โ”‚ ๆทปๅŠ ่Š‚็‚น     โ”‚     โ”‚ ๅฏๅŠจ     โ”‚
          โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                                                                        โ”‚
                                                                        โ–ผ
                                                                 โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                                                                 โ”‚ ่ฏทๆฑ‚่ขซๅค„็†   โ”‚
                                                                 โ”‚ (~1.5-3s     โ”‚
                                                                 โ”‚  ๅ†ทๅฏๅŠจ)     โ”‚
                                                                 โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

          ๆ—ถ้—ด็บฟ:
          โ”œโ”€โ”€ ๆต้‡ๅœๆญข โ”€โ”€โ”คโ”€โ”€ 15-30s ๅฎฝ้™ๆœŸ โ”€โ”€โ”คโ”€โ”€ 60s ็จณๅฎš็ช—ๅฃ โ”€โ”€โ”คโ”€โ”€ ่Š‚็‚น็ฉบ้—ฒ 10m โ”€โ”€โ”ค
          โ”‚              โ”‚ pods ไปๅœจ่ฟ่กŒ     โ”‚ pods ็ปˆๆญข         โ”‚ ่Š‚็‚น่ขซ็งป้™ค       โ”‚
          โ”‚              โ”‚ (ๅฏ้…็ฝฎ)          โ”‚ (scale-to-zero)   โ”‚ (้›†็พค่‡ชๅŠจ็ผฉๅฎน)   โ”‚

Step 2.3: ้…็ฝฎ Knative Service ไฝฟ็”จไธ“็”จๆœบๅ™จๆฑ 

apiVersion: serving.knative.dev/v1
        kind: Service
        metadata:
          name: my-function
          namespace: my-project
        spec:
          template:
            spec:
              tolerations:
                - key: "serverless"
                  operator: "Equal"
                  value: "true"
                  effect: "NoSchedule"
              nodeSelector:
                node-role.kubernetes.io/serverless: ""
              containers:
                - image: <registry>/<project>/my-function:latest
                  resources:
                    requests:
                      cpu: 100m
                      memory: 128Mi
                    limits:
                      cpu: 500m
                      memory: 256Mi

ๅฎ˜ๆ–นๆ–‡ๆกฃ: ROSA ๆœบๅ™จๆฑ ็ฎก็†


Phase 3: Lambda ๅˆฐ Knative ่ฟ็งป๏ผˆ็ฌฌ 3-5 ๅ‘จ๏ผ‰

Step 3.1: Lambda ๆฆ‚ๅฟตๆ˜ ๅฐ„

AWS Lambda ๆฆ‚ๅฟต Knative / OpenShift ็ญ‰ไปท็‰ฉ
Lambda Function Knative Service (ksvc)
Lambda Handler ๅฎนๅ™จๅ…ฅๅฃ็‚น / HTTP handler
API Gateway trigger Knative Route๏ผˆ้š ksvc ่‡ชๅŠจๅˆ›ๅปบ๏ผ‰
SQS trigger KafkaSource / SinkBinding + AMQ Streams
S3 trigger SinkBinding via Knative Eventing
Schedule trigger (EventBridge) PingSource
DynamoDB trigger ่‡ชๅฎšไน‰ Source ๆˆ– Change Data Capture
SNS trigger Knative Channel + Subscription
Env variables ConfigMap / Secret ๅผ•็”จ
Lambda Layers ๅคš้˜ถๆฎตๅฎนๅ™จๆž„ๅปบ๏ผˆๅ…ฑไบซๅŸบ็ก€้•œๅƒ๏ผ‰
Concurrency limit containerConcurrency ๅญ—ๆฎต
Timeout timeoutSeconds ๅญ—ๆฎต
Cold start ไผ˜ๅŒ– minScale โ‰ฅ 1๏ผˆไฟๆŒ 1 ไธช pod ้ข„็ƒญ๏ผ‰
Versioning/Alias Knative Revisions + Traffic Splitting
X-Ray tracing OpenTelemetry Collector
CloudWatch logs OpenShift Logging / ้›†็พคๆ—ฅๅฟ—
AWS SAM template Knative Service YAML + Tekton Pipeline
AWS CDK Helm Chart / Kustomize + ArgoCD
aws lambda invoke curl https://<ksvc-route> ๆˆ– kn service invoke

Step 3.2: ่ฝฌๆข Lambda ๅ‡ฝๆ•ฐไธบ Knative Service

ๅŽŸๅง‹ Lambda ๅ‡ฝๆ•ฐ (lambda_function.py):

import json
        import time
        import os
        import platform
        
        COLD_START = True
        
        def lambda_handler(event, context):
            global COLD_START
            was_cold = COLD_START
            COLD_START = False
            
            name = "World"
            qs = event.get("queryStringParameters") or {}
            if isinstance(qs, dict) and qs.get("name"):
                name = qs["name"]
            
            return {
                "statusCode": 200,
                "headers": {"Content-Type": "application/json"},
                "body": json.dumps({
                    "message": f"Hello, {name}!",
                    "platform": "AWS Lambda",
                    "cold_start": was_cold
                })
            }

่ฝฌๆขไธบ Knative ๅ…ผๅฎน็š„ HTTP ๆœๅŠก (app.py):

from flask import Flask, request, jsonify
        import os
        import time
        import platform
        
        app = Flask(__name__)
        COLD_START = True
        
        @app.route("/", methods=["GET", "POST"])
        def handler():
            global COLD_START
            was_cold = COLD_START
            COLD_START = False
            
            if request.method == "POST":
                event = request.get_json(silent=True) or {}
                name = event.get("name", "World")
            else:
                name = request.args.get("name", "World")
            
            return jsonify({
                "message": f"Hello, {name}!",
                "platform": "OpenShift Serverless (Knative)",
                "cold_start": was_cold,
                "pod_name": os.environ.get("HOSTNAME", "unknown")
            })
        
        if __name__ == "__main__":
            port = int(os.environ.get("PORT", 8080))
            app.run(host="0.0.0.0", port=port)

Dockerfile:

FROM registry.access.redhat.com/ubi9/python-311:latest
        WORKDIR /app
        COPY requirements.txt .
        RUN pip install --no-cache-dir -r requirements.txt
        COPY app.py .
        EXPOSE 8080
        CMD ["python", "app.py"]

Knative Service YAML (knative-service.yaml):

apiVersion: serving.knative.dev/v1
        kind: Service
        metadata:
          name: hello-function
          namespace: serverless-demo
          labels:
            app.kubernetes.io/part-of: serverless-functions
        spec:
          template:
            metadata:
              annotations:
                autoscaling.knative.dev/min-scale: "0"        # ็ฉบ้—ฒๆ—ถ็ผฉ้›ถ
                autoscaling.knative.dev/max-scale: "10"        # ๆœ€ๅคง pod ๆ•ฐ
                autoscaling.knative.dev/target: "50"           # ๆฏ pod 50 ๅนถๅ‘
                autoscaling.knative.dev/scale-down-delay: "15s"
            spec:
              containerConcurrency: 50
              timeoutSeconds: 300
              containers:
                - image: <registry>/hello-function:latest
                  ports:
                    - containerPort: 8080
                  resources:
                    requests:
                      cpu: 100m
                      memory: 128Mi
                    limits:
                      cpu: 500m
                      memory: 256Mi
                  readinessProbe:
                    httpGet:
                      path: /
                    initialDelaySeconds: 0

ๅฎžๆต‹: ้ƒจ็ฝฒๅŽ็บฆ 10 ็ง’ๅณๅฐฑ็ปช๏ผŒ่‡ชๅŠจ็”Ÿๆˆ HTTPS ่ทฏ็”ฑใ€‚


        # ๅฎžๆต‹่พ“ๅ‡บ
        
        $ oc get ksvc -n serverless-demo
        NAME             URL                                                                                     LATESTCREATED          LATESTREADY            READY
        hello-function   https://hello-function-serverless-demo.apps.rosa.rosa-fhmhp.r63a.p3.openshiftapps.com   hello-function-00001   hello-function-00001   True
        
        # ็ƒญ่ฏทๆฑ‚ๆต‹่ฏ•
        
        $ time curl -sk "https://hello-function-serverless-demo.apps.rosa.rosa-fhmhp.r63a.p3.openshiftapps.com"
        Hi  greeter => '9861675f8845' : 5
        real    0m0.030s
        
        $ time curl -sk "https://hello-function-serverless-demo.apps.rosa.rosa-fhmhp.r63a.p3.openshiftapps.com"
        Hi  greeter => '9861675f8845' : 6
        real    0m0.029s
        
        # ้ชŒ่ฏ Scale-to-Zero๏ผˆ็ญ‰ๅพ…็บฆ 120 ็ง’ๅŽ๏ผ‰
        
        $ oc get pods -n serverless-demo
        No resources found in serverless-demo namespace.    โ† Pod ๅทฒ่ขซ็งป้™ค
        
        $ oc get revisions -n serverless-demo
        NAME                   CONFIG NAME      GENERATION   READY   ACTUAL REPLICAS   DESIRED REPLICAS
        hello-function-00001   hello-function   1            True    0                 0
        
        # โœ… Scale-to-Zero ้ชŒ่ฏๆˆๅŠŸ๏ผšACTUAL REPLICAS = 0
        
        # ๅ†ทๅฏๅŠจๆต‹่ฏ•๏ผˆไปŽ้›ถๆ‰ฉๅฎน๏ผ‰
        
        $ time curl -sk "https://hello-function-serverless-demo.apps.rosa.rosa-fhmhp.r63a.p3.openshiftapps.com"
        Hi  greeter => '9861675f8845' : 3
        real    0m1.668s    โ† ๅ†ทๅฏๅŠจ ~1.67s
        
        $ time curl -sk "https://hello-function-serverless-demo.apps.rosa.rosa-fhmhp.r63a.p3.openshiftapps.com"
        Hi  greeter => '9861675f8845' : 4
        real    0m0.030s    โ† ็ƒญ่ฏทๆฑ‚ๆขๅคๅˆฐ ~30ms

Step 3.3: Knative Functions (kn func) โ€” ็œŸๆญฃ็š„ Lambda ็ญ‰ไปทๅผ€ๅ‘ไฝ“้ชŒ

Phase 3.2 ไฝฟ็”จไบ†ไธ€ไธช้ข„ๆž„ๅปบ็š„ๅฎนๅ™จ้•œๅƒ็›ดๆŽฅ้ƒจ็ฝฒไธบ Knative Serviceใ€‚ไฝ† AWS Lambda ็š„ๅผ€ๅ‘ไฝ“้ชŒๆ˜ฏ โ€œๅชๅ†™ๅ‡ฝๆ•ฐไปฃ็ ๏ผŒไธๅ…ณๅฟƒๅฎนๅ™จโ€ใ€‚

kn func (Knative Functions) ๆไพ›ไบ†ๅฎŒๅ…จ็ญ‰ไปท็š„ไฝ“้ชŒ๏ผšๅชๅ†™ๅ‡ฝๆ•ฐไปฃ็  โ†’ ่‡ชๅŠจๆž„ๅปบ้•œๅƒ (S2I) โ†’ ้ƒจ็ฝฒไธบ Knative Service๏ผŒๆ— ้œ€ Dockerfileใ€‚

Step 1: ๅˆ›ๅปบๅ‡ฝๆ•ฐ้กน็›ฎ


        # ๅฎ‰่ฃ… kn CLI๏ผˆOpenShift Serverless 1.37 ้…ๅฅ—็‰ˆๆœฌ๏ผ‰
        
        $ curl -sL https://mirror.openshift.com/pub/openshift-v4/clients/serverless/1.17.0/kn-linux-amd64.tar.gz \
          | tar xz -C /tmp/
        $ /tmp/kn version
        Version:      v1.17.0
        Build Date:   2025-04-22 16:39:02
        
        # ๅˆ›ๅปบ Python ๅ‡ฝๆ•ฐ้กน็›ฎ๏ผˆ่‡ชๅŠจ็”Ÿๆˆ้ชจๆžถไปฃ็ ๏ผ‰
        
        $ /tmp/kn func create -l python hello-func
        Created python function in /tmp/hello-func
        
        $ ls /tmp/hello-func/
        .funcignore  func.yaml  function/  requirements.txt
        
        # ๆณจๆ„๏ผšๆฒกๆœ‰ Dockerfile๏ผไฝฟ็”จ S2I (Source-to-Image) ่‡ชๅŠจๆž„ๅปบ

Step 2: ็ผ–ๅ†™ๅ‡ฝๆ•ฐไปฃ็ 


        # function/func.py โ€” ASGI ๅ่ฎฎ๏ผŒไธŽ Lambda handler ็ญ‰ไปท
        
        import json, os, time
        
        COLD_START = True
        
        def new():
            return Function()
        
        class Function:
            async def handle(self, scope, receive, send):
                global COLD_START
                was_cold = COLD_START
                COLD_START = False
                start = time.time()
        
                # ่ฏปๅ–่ฏทๆฑ‚ body
                body = b""
                while True:
                    msg = await receive()
                    body += msg.get("body", b"")
                    if not msg.get("more_body"): break
        
                # ่งฃๆžๅ‚ๆ•ฐ๏ผˆๆ”ฏๆŒ query string ๅ’Œ JSON body๏ผ‰
                name = "World"
                qs = scope.get("query_string", b"").decode()
                for param in qs.split("&"):
                    if param.startswith("name="): name = param.split("=", 1)[1]; break
                if body:
                    try: data = json.loads(body); name = data.get("name", name)
                    except: pass
        
                # ๆž„ๅปบๅ“ๅบ”
                elapsed = (time.time() - start) * 1000
                resp = json.dumps({
                    "message": f"Hello, {name}!",
                    "platform": "OpenShift Serverless Function (kn func)",
                    "cold_start": was_cold,
                    "processing_time_ms": round(elapsed, 2),
                    "pod_name": os.environ.get("HOSTNAME", "unknown")
                })
        
                await send({"type": "http.response.start", "status": 200,
                             "headers": [[b"content-type", b"application/json"]]})
                await send({"type": "http.response.body", "body": resp.encode()})

Step 3: ๆž„ๅปบ & ้ƒจ็ฝฒ


        # ๆšด้œฒ OpenShift ๅ†…้ƒจ้•œๅƒไป“ๅบ“
        
        $ oc patch configs.imageregistry.operator.openshift.io/cluster --type merge \
          -p '{"spec":{"defaultRoute":true}}'
        
        $ REGISTRY_HOST=$(oc get route default-route -n openshift-image-registry -o jsonpath='{.spec.host}')
        
        # ๆž„ๅปบ้•œๅƒ๏ผˆS2I ่‡ชๅŠจๆž„ๅปบ๏ผŒๆ— ้œ€ Dockerfile๏ผ๏ผ‰
        
        $ cd /tmp/hello-func
        $ /tmp/kn func build -r "$REGISTRY_HOST/serverless-demo" -v
        ๐Ÿ™Œ Function built: default-route-openshift-image-registry.apps.rosa.rosa-fhmhp.r63a.p3.openshiftapps.com/serverless-demo/hello-func:latest
        
        # ๆŽจ้€้•œๅƒๅˆฐๅ†…้ƒจ Registry
        
        $ TOKEN=$(oc whoami -t)
        $ podman login "$REGISTRY_HOST" -u kubeadmin -p "$TOKEN" --tls-verify=false
        Login Succeeded!
        
        $ podman push "$REGISTRY_HOST/serverless-demo/hello-func:latest" --tls-verify=false
        Writing manifest to image destination
        
        # ้ƒจ็ฝฒไธบ Knative Service๏ผˆไฝฟ็”จ้›†็พคๅ†…้ƒจ registry ๅœฐๅ€๏ผ‰
        
        $ /tmp/kn service create hello-func \
          --image image-registry.openshift-image-registry.svc:5000/serverless-demo/hello-func:latest \
          -n serverless-demo \
          --annotation autoscaling.knative.dev/min-scale=0 \
          --annotation autoscaling.knative.dev/max-scale=10
        Creating service 'hello-func' in namespace 'serverless-demo':
         12.036s Ready to serve.
        
        Service 'hello-func' created to latest revision 'hello-func-00001' is available at URL:
        https://hello-func-serverless-demo.apps.rosa.rosa-fhmhp.r63a.p3.openshiftapps.com

Step 3b: ๆž„ๅปบ โ€” ๆ–นๆณ•ไบŒ๏ผšDockerfile (้€š็”จๆ–นๆณ•๏ผŒๆ— ๅŽ‚ๅ•†ไพ่ต–)

S2I (Source-to-Image) ๆ˜ฏ Red Hat ็‰นๆœ‰็š„ๆž„ๅปบๆŠ€ๆœฏใ€‚ๅฆ‚ๆžœๆ‚จ็š„ๅ›ข้˜Ÿๆ›ดไน ๆƒฏๆ ‡ๅ‡† Dockerfile ๅทฅไฝœๆต๏ผŒๆˆ–่€…้œ€่ฆๅœจ้ž OpenShift ็Žฏๅขƒไธญๆž„ๅปบ้•œๅƒ๏ผŒๅฏไปฅไฝฟ็”จไปฅไธ‹ Dockerfile ๆ–นๆณ•ใ€‚

ๅบ•ๅฑ‚่ฟ่กŒๆ—ถๅฎŒๅ…จ็›ธๅŒ๏ผš้ƒฝไฝฟ็”จๅผ€ๆบ็š„ func-python ๅŒ…๏ผˆApache-2.0 ่ฎธๅฏ่ฏ๏ผ‰๏ผŒๅ†…็ฝฎ hypercorn ASGI ๆœๅŠกๅ™จใ€‚


        # ๅˆ›ๅปบ Dockerfile๏ผˆ็ญ‰ไปทไบŽ S2I ่‡ชๅŠจ็”Ÿๆˆ็š„ๆž„ๅปบ้€ป่พ‘๏ผ‰
        
        cat > /tmp/hello-func/Dockerfile <<'DOCKERFILE'
        FROM registry.access.redhat.com/ubi9/python-312:latest
        WORKDIR /opt/app-root/src
        COPY requirements.txt .
        RUN pip install --no-cache-dir -r requirements.txt
        COPY function/ ./function/
        COPY main.py .
        EXPOSE 8080
        CMD ["python", "main.py"]
        DOCKERFILE
        
        # ๅˆ›ๅปบๅ…ฅๅฃๆ–‡ไปถ main.py๏ผˆไธŽ S2I ๅ†…้ƒจ็”Ÿๆˆ็š„ๅ…ฅๅฃไธ€่‡ด๏ผ‰
        
        cat > /tmp/hello-func/main.py <<'MAIN'
        import logging
        from func_python.http import serve
        logging.basicConfig(level=logging.INFO)
        try:
            from function import new as handler
        except ImportError:
            from function import handle as handler
        if __name__ == "__main__":
            logging.info("Functions middleware invoking user function")
            serve(handler)
        MAIN
        
        # ็กฎไฟ function/__init__.py ๅฏผๅ‡บๆญฃ็กฎ
        
        cat > /tmp/hello-func/function/__init__.py <<'INIT'
        from .func import new
        INIT
        
        # ไฝฟ็”จ podman ๆž„ๅปบ้•œๅƒ
        
        $ cd /tmp/hello-func
        $ podman build -t "$REGISTRY_HOST/serverless-demo/hello-func:dockerfile" .
        STEP 1/7: FROM registry.access.redhat.com/ubi9/python-312:latest
        STEP 2/7: WORKDIR /opt/app-root/src
        STEP 3/7: COPY requirements.txt .
        STEP 4/7: RUN pip install --no-cache-dir -r requirements.txt
        Successfully installed ...
        STEP 5/7: COPY function/ ./function/
        STEP 6/7: COPY main.py .
        STEP 7/7: EXPOSE 8080
        COMMIT default-route-openshift-image-registry.apps.rosa.rosa-fhmhp.r63a.p3.openshiftapps.com/serverless-demo/hello-func:dockerfile
        Successfully tagged ...
        
        # ๆŽจ้€ & ้ƒจ็ฝฒ
        
        $ podman push "$REGISTRY_HOST/serverless-demo/hello-func:dockerfile" --tls-verify=false
        Writing manifest to image destination
        
        $ /tmp/kn service create hello-func \
          --image image-registry.openshift-image-registry.svc:5000/serverless-demo/hello-func:dockerfile \
          -n serverless-demo --force \
          --annotation autoscaling.knative.dev/min-scale=0 \
          --annotation autoscaling.knative.dev/max-scale=10
        Service 'hello-func' created to latest revision 'hello-func-00001' is available at URL:
        https://hello-func-serverless-demo.apps.rosa.rosa-fhmhp.r63a.p3.openshiftapps.com
        
        # ้ชŒ่ฏ๏ผˆๆ€ง่ƒฝไธŽ S2I ็‰ˆๅฎŒๅ…จไธ€่‡ด๏ผ‰
        
        $ time curl -sk "$FUNC_URL?name=Demo"
        {"message": "Hello, Demo!", "platform": "OpenShift Serverless Function (Dockerfile)",
         "cold_start": true, "processing_time_ms": 0.01,
         "pod_name": "hello-func-00001-deployment-5cf64484f9-vxbl8"}
        real    0m0.031s
        
        $ time curl -sk "$FUNC_URL?name=Dockerfile"
        {"message": "Hello, Dockerfile!", "platform": "OpenShift Serverless Function (Dockerfile)",
         "cold_start": false, "processing_time_ms": 0.01, ...}
        real    0m0.026s

ไธค็งๆž„ๅปบๆ–นๅผๅฏนๆฏ”:

็ปดๅบฆ S2I (kn func build) Dockerfile (podman build)
ๆž„ๅปบๅทฅๅ…ท kn func build (ๅ†…็ฝฎ S2I) podman build / docker build
Dockerfile โŒ ไธ้œ€่ฆ๏ผˆ่‡ชๅŠจ็”Ÿๆˆ๏ผ‰ โœ… ้œ€่ฆ็ผ–ๅ†™
ๅ…ฅๅฃๆ–‡ไปถ โŒ ไธ้œ€่ฆ๏ผˆS2I ่‡ชๅŠจๆณจๅ…ฅ๏ผ‰ โœ… ้œ€่ฆ main.py
่ฟ่กŒๆ—ถ func-python + hypercorn func-python + hypercorn (ๅฎŒๅ…จ็›ธๅŒ)
OpenShift ไพ่ต– ้œ€่ฆ S2I builder image ๆ— ไพ่ต–๏ผŒไปปไฝ•ๅฎนๅ™จๅผ•ๆ“Žๅ‡ๅฏ
CI/CD ้›†ๆˆ OpenShift Pipelines (S2I task) ้€š็”จ (Buildah / Kaniko / Docker)
็ฆป็บฟๆž„ๅปบ ้œ€่ฆ S2I builder ้•œๅƒ ไป…้œ€ UBI ๅŸบ็ก€้•œๅƒ
ๆž„ๅปบ้€Ÿๅบฆ ~15-20s ~10-15s
้€‚็”จๅœบๆ™ฏ OpenShift ๅŽŸ็”Ÿๅผ€ๅ‘ ๅคšๅนณๅฐ / ๆททๅˆ็Žฏๅขƒ / ๆ ‡ๅ‡†ๅŒ–ๆต็จ‹

ๅปบ่ฎฎ: ๅฆ‚ๆžœๅ›ข้˜Ÿๅทฒๆœ‰ๆ ‡ๅ‡†ๅŒ–็š„ Dockerfile + CI/CD ๆต็จ‹๏ผˆๅฆ‚ Jenkinsใ€GitLab CI๏ผ‰๏ผŒๆŽจ่ไฝฟ็”จ Dockerfile ๆ–นๆณ•๏ผ›ๅฆ‚ๆžœๅ…จๆ ˆไฝฟ็”จ OpenShift๏ผŒS2I ๆ–นๆณ•ๆ›ด็ฎ€ๆดใ€‚ไธค่€…็”Ÿๆˆ็š„้•œๅƒ่ฟ่กŒๆ—ถๅฎŒๅ…จ็›ธๅŒ๏ผŒๆ€ง่ƒฝๆ— ๅทฎๅผ‚ใ€‚

Step 3c: ๅœจ Web Console ไธญๆ˜พ็คบไธบ Function

้—ฎ้ข˜: ไฝฟ็”จ kn service create ๆ‰‹ๅŠจ้ƒจ็ฝฒ็š„ Knative Service๏ผŒๅœจ OpenShift Web Console ็š„ Serverless โ†’ Functions ่ง†ๅ›พไธญไธไผšๆ˜พ็คบใ€‚

ๅŽŸๅ› : Web Console ไพ่ต–็‰นๅฎš็š„ label ๆฅ่ฏ†ๅˆซ โ€œFunctionโ€ใ€‚kn service create ๅชๅˆ›ๅปบๆ™ฎ้€š็š„ Knative Service๏ผŒไธไผš่‡ชๅŠจๆทปๅŠ ่ฟ™ไบ› labelใ€‚


        # ๆ–นๆณ•ไธ€๏ผšๆ‰‹ๅŠจๆทปๅŠ  label๏ผˆ้€‚็”จไบŽๅทฒ้ƒจ็ฝฒ็š„ Service๏ผ‰
        
        $ oc label ksvc hello-func \
          function.knative.dev=true \
          function.knative.dev/name=hello-func \
          boson.dev/function=true \
          -n serverless-demo
        service.serving.knative.dev/hello-func labeled
        
        # ้ชŒ่ฏ label
        
        $ oc get ksvc hello-func -n serverless-demo -o jsonpath='{.metadata.labels}' | jq .
        {
          "boson.dev/function": "true",
          "function.knative.dev": "true",
          "function.knative.dev/name": "hello-func"
        }
        
        # โœ… ๅˆทๆ–ฐ Web Console โ†’ Serverless โ†’ Functions๏ผŒๅณๅฏ็œ‹ๅˆฐ hello-func

ๆ›ฟไปฃๆ–นๆกˆ: kn func deploy โ€” ๅฆ‚ๆžœไฝฟ็”จ kn func deploy ไปฃๆ›ฟๆ‰‹ๅŠจ็š„ build + push + create ไธ‰ๆญฅๆ“ไฝœ๏ผŒ

ๅฎƒไผš่‡ชๅŠจๅฎŒๆˆ ๆž„ๅปบ + ๆŽจ้€ + ้ƒจ็ฝฒ + ๆทปๅŠ  function label๏ผŒๆ˜ฏๆœ€็ฎ€ไพฟ็š„ๆ–นๅผ๏ผš


        # ๅœจๅ‡ฝๆ•ฐ้กน็›ฎ็›ฎๅฝ•ไธญไธ€ๆญฅๅฎŒๆˆ๏ผˆ่‡ชๅŠจๆทปๅŠ  function label๏ผ‰
        
        cd /tmp/hello-func
        
        /tmp/kn func deploy -r "$REGISTRY_HOST/serverless-demo" -n serverless-demo
        
        # ็ญ‰ไปทไบŽ: kn func build + podman push + kn service create + ่‡ชๅŠจๆทปๅŠ  function labels

ไธค่€…ๅŠŸ่ƒฝๅฎŒๅ…จ็›ธๅŒ๏ผŒlabel ๅชๅฝฑๅ“ Web Console ็š„ๅฑ•็คบๅˆ†็ฑป๏ผŒไธๅฝฑๅ“่ฟ่กŒๆ—ถ่กŒไธบใ€‚

Step 4: ๆต‹่ฏ•

FUNC_URL="https://hello-func-serverless-demo.apps.rosa.rosa-fhmhp.r63a.p3.openshiftapps.com"
        
        # GET ่ฏทๆฑ‚
        
        $ time curl -sk "$FUNC_URL?name=Demo"
        {"message": "Hello, Demo!", "platform": "OpenShift Serverless Function (kn func)",
         "cold_start": true, "processing_time_ms": 0.01,
         "pod_name": "hello-func-00001-deployment-5c4c9b46c9-5s4mc"}
        real    0m0.038s
        
        # ็ƒญ่ฏทๆฑ‚
        
        $ time curl -sk "$FUNC_URL?name=OpenShift"
        {"message": "Hello, OpenShift!", "platform": "OpenShift Serverless Function (kn func)",
         "cold_start": false, "processing_time_ms": 0.01, ...}
        real    0m0.031s
        
        # POST ่ฏทๆฑ‚๏ผˆJSON body๏ผ‰
        
        $ time curl -sk -X POST "$FUNC_URL" -H "Content-Type: application/json" \
          -d '{"name":"KnativeFunction"}'
        {"message": "Hello, KnativeFunction!", "platform": "OpenShift Serverless Function (kn func)",
         "cold_start": false, "processing_time_ms": 0.03, ...}
        real    0m0.030s

kn func ๅผ€ๅ‘ไฝ“้ชŒ vs Lambda ๅฏนๆฏ”:

ๆญฅ้ชค AWS Lambda kn func (Knative Functions)
่„šๆ‰‹ๆžถ sam init kn func create -l python
ๅ†™ไปฃ็  lambda_handler(event, context) Function.handle(scope, receive, send)
ๆž„ๅปบ sam build / zip ๆ‰“ๅŒ… kn func build (S2I, ๆ— ้œ€ Dockerfile)
้ƒจ็ฝฒ sam deploy + IAM + API GW kn service create --image ...
Dockerfile โŒ ไธ้œ€่ฆ โŒ ไธ้œ€่ฆ (S2I ่‡ชๅŠจๆž„ๅปบ)
SDK ไพ่ต– AWS SDK, boto3 ๆ—  (ๆ ‡ๅ‡† HTTP/ASGI)
ๆ”ฏๆŒ่ฏญ่จ€ Python/Node/Go/Java/โ€ฆ Python/Node/Go/Quarkus/Rust/TypeScript
็ƒญ่ฏทๆฑ‚ๅปถ่ฟŸ ~44-55ms ~28-31ms
ๅคšไบ‘ โŒ ไป… AWS โœ… ไปปไฝ• OCP ้›†็พค

็ป“่ฎบ: kn func ๆไพ›ไบ†ไธŽ Lambda ๅฎŒๅ…จ็ญ‰ไปท็š„ โ€œๅชๅ†™ไปฃ็ ๏ผŒไธๅ…ณๅฟƒๅฎนๅ™จโ€ ๅผ€ๅ‘ไฝ“้ชŒ๏ผŒๅŒๆ—ถไฟๆŒๅคšไบ‘ๅฏ็งปๆคๆ€งใ€‚

ๅฎ˜ๆ–นๆ–‡ๆกฃ: Knative Functions (kn func)


Phase 4: ็ปŸไธ€ CI/CD ็ฎก้“๏ผˆ็ฌฌ 4-6 ๅ‘จ๏ผ‰

Step 4.1: CI/CD ๆžถๆž„

  ๅผ€ๅ‘่€…                                                    
          โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”       โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”       โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
          โ”‚ Git   โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ–ถโ”‚ Git Repo  โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ–ถโ”‚ Tekton EventListener                  โ”‚
          โ”‚ Push  โ”‚       โ”‚ (GitHub/  โ”‚       โ”‚ (webhook ่งฆๅ‘)                        โ”‚
          โ”‚       โ”‚       โ”‚  GitLab)  โ”‚       โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
          โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜       โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                  โ”‚
                                                         โ–ผ
                                            โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                                            โ”‚ Tekton Pipeline Run    โ”‚
                                            โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                                                         โ”‚
                          โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                          โ–ผ                              โ–ผ                         โ–ผ
                โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”          โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”      โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                โ”‚ Task: Clone     โ”‚          โ”‚ Task: Build &    โ”‚      โ”‚ Task: Deploy   โ”‚
                โ”‚ Source Code     โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ถ โ”‚ Push Image       โ”‚โ”€โ”€โ”€โ”€โ”€โ–ถโ”‚ via GitOps     โ”‚
                โ”‚                 โ”‚          โ”‚ (Buildah/s2i)    โ”‚      โ”‚ (ArgoCD sync)  โ”‚
                โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜          โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜      โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                                                     โ”‚                         โ”‚
                                                     โ–ผ                         โ–ผ
                                            โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                                            โ”‚ Quay.io /        โ”‚    โ”‚ GitOps Repo         โ”‚
                                            โ”‚ Internal Registryโ”‚    โ”‚ (kustomize overlay  โ”‚
                                            โ”‚                  โ”‚    โ”‚  per environment)   โ”‚
                                            โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                                                                               โ”‚
                                                 โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                                                 โ–ผ                             โ–ผ          โ–ผ
                                          โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”           โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                                          โ”‚ ROSA (AWS)  โ”‚           โ”‚ ARO (Azure)  โ”‚ โ”‚ OCP     โ”‚
                                          โ”‚ Knative Svc โ”‚           โ”‚ Knative Svc  โ”‚ โ”‚ (Ali/   โ”‚
                                          โ”‚ deployed    โ”‚           โ”‚ deployed     โ”‚ โ”‚  GCP)   โ”‚
                                          โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜           โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Step 4.2: Tekton Pipeline ๅฎšไน‰

apiVersion: tekton.dev/v1
        kind: Pipeline
        metadata:
          name: serverless-function-pipeline
          namespace: serverless-cicd
        spec:
          params:
            - name: git-url
              type: string
            - name: git-revision
              type: string
              default: main
            - name: function-name
              type: string
            - name: image-registry
              type: string
              default: quay.io/my-org
            - name: target-namespace
              type: string
              default: serverless-demo
          workspaces:
            - name: shared-workspace
            - name: docker-credentials
          tasks:
            - name: fetch-source
              taskRef:
                name: git-clone
                kind: ClusterTask
              workspaces:
                - name: output
                  workspace: shared-workspace
              params:
                - name: url
                  value: $(params.git-url)
                - name: revision
                  value: $(params.git-revision)
            - name: build-image
              taskRef:
                name: buildah
                kind: ClusterTask
              runAfter: [fetch-source]
              workspaces:
                - name: source
                  workspace: shared-workspace
                - name: dockerconfig
                  workspace: docker-credentials
              params:
                - name: IMAGE
                  value: "$(params.image-registry)/$(params.function-name):$(params.git-revision)"
            - name: deploy-knative-service
              taskRef:
                name: openshift-client
                kind: ClusterTask
              runAfter: [build-image]
              params:
                - name: SCRIPT
                  value: |
                    oc apply -f knative-service.yaml -n $(params.target-namespace)

Step 4.3: GitOps ไป“ๅบ“็ป“ๆž„

serverless-gitops/
        โ”œโ”€โ”€ base/
        โ”‚   โ”œโ”€โ”€ kustomization.yaml
        โ”‚   โ””โ”€โ”€ knative-service-template.yaml
        โ”œโ”€โ”€ functions/
        โ”‚   โ”œโ”€โ”€ hello-function/
        โ”‚   โ”‚   โ”œโ”€โ”€ kustomization.yaml
        โ”‚   โ”‚   โ””โ”€โ”€ knative-service.yaml
        โ”‚   โ”œโ”€โ”€ order-processor/
        โ”‚   โ”‚   โ”œโ”€โ”€ kustomization.yaml
        โ”‚   โ”‚   โ””โ”€โ”€ knative-service.yaml
        โ”‚   โ””โ”€โ”€ notification-sender/
        โ”‚       โ”œโ”€โ”€ kustomization.yaml
        โ”‚       โ””โ”€โ”€ knative-service.yaml
        โ”œโ”€โ”€ overlays/
        โ”‚   โ”œโ”€โ”€ rosa-prod/
        โ”‚   โ”‚   โ”œโ”€โ”€ kustomization.yaml
        โ”‚   โ”‚   โ””โ”€โ”€ patches/
        โ”‚   โ”‚       โ””โ”€โ”€ scale-config.yaml        # minScale=0, maxScale=100
        โ”‚   โ”œโ”€โ”€ aro-prod/
        โ”‚   โ”‚   โ”œโ”€โ”€ kustomization.yaml
        โ”‚   โ”‚   โ””โ”€โ”€ patches/
        โ”‚   โ”‚       โ”œโ”€โ”€ scale-config.yaml
        โ”‚   โ”‚       โ””โ”€โ”€ registry-override.yaml   # Azure Container Registry
        โ”‚   โ””โ”€โ”€ ocp-ali-prod/
        โ”‚       โ”œโ”€โ”€ kustomization.yaml
        โ”‚       โ””โ”€โ”€ patches/
        โ”‚           โ””โ”€โ”€ registry-override.yaml   # ้˜ฟ้‡Œไบ‘ Registry
        โ””โ”€โ”€ argocd/
            โ”œโ”€โ”€ rosa-prod-app.yaml
            โ”œโ”€โ”€ aro-prod-app.yaml
            โ””โ”€โ”€ ocp-ali-prod-app.yaml

ๅฎ˜ๆ–นๆ–‡ๆกฃ: OpenShift Pipelines (Tekton)


Phase 5: ไบ‹ไปถๆบ้›†ๆˆ๏ผˆ็ฌฌ 5-7 ๅ‘จ๏ผ‰

Step 5.1: Knative Eventing ๆžถๆž„ โ€” ๆ›ฟๆข Lambda ่งฆๅ‘ๅ™จ

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
        โ”‚                  Knative Eventing ๆžถๆž„                                       โ”‚
        โ”‚                                                                             โ”‚
        โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                                   โ”‚
        โ”‚  โ”‚   ไบ‹ไปถๆบ              โ”‚                                                   โ”‚
        โ”‚  โ”‚                       โ”‚                                                   โ”‚
        โ”‚  โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”‚
        โ”‚  โ”‚  โ”‚ PingSource      โ”‚โ”€โ”€โ”‚โ”€โ”€โ”€โ”€โ–ถโ”‚              โ”‚โ”€โ”€โ”€โ”€โ–ถโ”‚ Knative Service  โ”‚    โ”‚
        โ”‚  โ”‚  โ”‚ (ๅฎšๆ—ถ่ฐƒๅบฆ)      โ”‚  โ”‚     โ”‚   Knative    โ”‚     โ”‚ (ๅฎšๆ—ถไปปๅŠกๅค„็†)   โ”‚    โ”‚
        โ”‚  โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚     โ”‚   Broker     โ”‚     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ”‚
        โ”‚  โ”‚                       โ”‚     โ”‚              โ”‚                             โ”‚
        โ”‚  โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚     โ”‚ (ๆŽฅๆ”ถๆ‰€ๆœ‰    โ”‚     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”‚
        โ”‚  โ”‚  โ”‚ KafkaSource     โ”‚โ”€โ”€โ”‚โ”€โ”€โ”€โ”€โ–ถโ”‚  ไบ‹ไปถ๏ผŒ้€š่ฟ‡  โ”‚โ”€โ”€โ”€โ”€โ–ถโ”‚ Knative Service  โ”‚    โ”‚
        โ”‚  โ”‚  โ”‚ (ๆ›ฟไปฃ SQS)      โ”‚  โ”‚     โ”‚  Trigger     โ”‚     โ”‚ (ๆถˆๆฏๅค„็†)       โ”‚    โ”‚
        โ”‚  โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚     โ”‚  ่ทฏ็”ฑๅˆ†ๅ‘)   โ”‚     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ”‚
        โ”‚  โ”‚                       โ”‚     โ”‚              โ”‚                             โ”‚
        โ”‚  โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚     โ”‚              โ”‚     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”‚
        โ”‚  โ”‚  โ”‚ ApiServerSource โ”‚โ”€โ”€โ”‚โ”€โ”€โ”€โ”€โ–ถโ”‚              โ”‚โ”€โ”€โ”€โ”€โ–ถโ”‚ Knative Service  โ”‚    โ”‚
        โ”‚  โ”‚  โ”‚ (K8s ไบ‹ไปถ)      โ”‚  โ”‚     โ”‚              โ”‚     โ”‚ (K8s ไบ‹ไปถ็›‘ๅฌ)   โ”‚    โ”‚
        โ”‚  โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ”‚
        โ”‚  โ”‚                       โ”‚                                                   โ”‚
        โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                                   โ”‚
        โ”‚                                                                             โ”‚
        โ”‚  CloudEvents ่ง„่Œƒ = ่ทจไบ‘็š„ๅฏ็งปๆคไบ‹ไปถๆ ผๅผ                                     โ”‚
        โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Step 5.2: PingSource โ€” ๆ›ฟไปฃ CloudWatch Events / EventBridge ๅฎšๆ—ถ่งฆๅ‘


        # ๆ›ฟไปฃ: AWS EventBridge rule โ†’ Lambda (cron)
        
        apiVersion: sources.knative.dev/v1
        kind: PingSource
        metadata:
          name: daily-report-trigger
          namespace: serverless-demo
        spec:
          schedule: "0 2 * * *"          # ๆฏๅคฉๅ‡Œๆ™จ 2 ็‚น
          contentType: "application/json"
          data: '{"action": "generate-daily-report"}'
          sink:
            ref:
              apiVersion: serving.knative.dev/v1
              kind: Service
              name: daily-report-function

ๅฎžๆต‹: PingSource ๅˆ›ๅปบๅŽ็ซ‹ๅณ็”Ÿๆ•ˆ๏ผŒๆŒ‰็…ง cron ่กจ่พพๅผ่‡ชๅŠจ่งฆๅ‘ Knative Serviceใ€‚

ๆณจๆ„ sink ๅญ—ๆฎต็›ดๆŽฅๆŒ‡ๅ‘ Knative Service๏ผŒ่ฟ™ๅฐฑๆ˜ฏ Direct Sink๏ผˆ็›ดๆŽฅๆŠ•้€’๏ผ‰ ๆจกๅผ โ€”โ€” ๆ— ้œ€ Brokerใ€Channel ๆˆ– Kafkaใ€‚

Step 5.2b: ไบ‹ไปถๆŠ•้€’ๆœบๅˆถ่ฏฆ่งฃ โ€” ไธบไป€ไนˆไธ้œ€่ฆ Kafka๏ผŸ

ๅธธ่ง็–‘้—ฎ: ้…็ฝฎไบ† Knative Eventing ไฝ†ๆฒกๆœ‰ๅฎ‰่ฃ… Kafka๏ผŒไบ‹ไปถๆ˜ฏๆ€ŽไนˆๆŠ•้€’็ป™ๆœๅŠก็ซฏ็š„๏ผŸ

็ญ”ๆกˆ๏ผšPingSource ไฝฟ็”จ Direct Sink ๆจกๅผ๏ผŒ็›ดๆŽฅ HTTP POST ๅˆฐ Knative Service ็š„ๅ†…้ƒจ URL๏ผŒๆ— ้œ€ไปปไฝ•ๆถˆๆฏไธญ้—ดไปถใ€‚

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    HTTP POST (CloudEvent)    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
        โ”‚ PingSource  โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ถ โ”‚ Knative Service     โ”‚
        โ”‚ (cron ่งฆๅ‘) โ”‚   ็›ดๆŽฅๅ‘้€ๅˆฐ้›†็พคๅ†…้ƒจ URL      โ”‚ daily-report-func   โ”‚
        โ”‚             โ”‚   ๆ— ไธญ้—ดไปถใ€ๆ—  Broker         โ”‚ .serverless-demo    โ”‚
        โ”‚             โ”‚   ๆ—  Channelใ€ๆ—  Kafka        โ”‚ .svc.cluster.local  โ”‚
        โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                               โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

ๆŠ•้€’่ฟ‡็จ‹๏ผš

  1. PingSource Controller ๆŒ‰ cron ่กจ่พพๅผ็”Ÿๆˆ CloudEvent
  2. ็›ดๆŽฅ HTTP POST ๅˆฐ http://<service-name>.<namespace>.svc.cluster.local
  3. Knative Service ๆ”ถๅˆฐ่ฏทๆฑ‚๏ผŒ่‹ฅ pod ไธบ 0 ๅˆ™่‡ชๅŠจ scale-from-zero
  4. ๆ•ดไธช้“พ่ทฏๆ— ไปปไฝ•ๆถˆๆฏไธญ้—ดไปถๅ‚ไธŽ

Knative Eventing ไธ‰็งไบ‹ไปถๆŠ•้€’ๆจกๅผ๏ผš

ๆจกๅผ ไธญ้—ดไปถ ้€‚็”จๅœบๆ™ฏ
1. Direct Sink ๆ—  1 ไธชไบ‹ไปถๆบ โ†’ 1 ไธชๆœๅŠก๏ผŒ็ฎ€ๅ•็‚นๅฏน็‚น
2. Channel + Subscription InMemoryChannel ๆˆ– KafkaChannel 1 โ†’ ๅคš๏ผˆๆ‰‡ๅ‡บ๏ผ‰๏ผŒๆŒ‰้กบๅบๆŠ•้€’
3. Broker + Trigger InMemoryChannel ๆˆ– KafkaChannel ๅคš โ†’ ๅคš๏ผŒๆŒ‰ๅฑžๆ€ง่ฟ‡ๆปค่ทฏ็”ฑ
ๆจกๅผไธ€ (Direct Sink):     PingSource โ”€โ”€HTTP POSTโ”€โ”€โ–ถ Service

        ๆจกๅผไบŒ (Channel/Sub):     PingSource โ”€โ”€โ–ถ Channel โ”€โ”€Subโ”€โ”€โ–ถ Service A
                                                          โ”€โ”€Subโ”€โ”€โ–ถ Service B

        ๆจกๅผไธ‰ (Broker/Trigger):  PingSource โ”€โ”€โ–ถ Broker โ”€โ”€Triggerโ”€โ”€โ–ถ Service A
                                  KafkaSourceโ”€โ”€โ–ถ        โ”€โ”€Triggerโ”€โ”€โ–ถ Service B

ๅ…ณไบŽ InMemoryChannel: ๅฎ‰่ฃ… Knative Eventing ๆ—ถ้…็ฝฎ็š„ InMemoryChannel ๆ˜ฏ้ป˜่ฎค็š„ Channel ๅฎž็Žฐ๏ผŒ

ไฝ†ๅชๆœ‰ๅœจไฝฟ็”จ Broker ๆˆ– Channel ๆจกๅผๆ—ถๆ‰ไผš่ขซๅˆ›ๅปบๅ’Œไฝฟ็”จใ€‚Direct Sink ๆจกๅผๅฎŒๅ…จไธๆถ‰ๅŠ Channelใ€‚

ไป€ไนˆๆ—ถๅ€™้œ€่ฆๅผ•ๅ…ฅ Kafka๏ผŸ

ๅœบๆ™ฏ ๆŽจ่
็ฎ€ๅ•ๅฎšๆ—ถ่งฆๅ‘ใ€็‚นๅฏน็‚นไบ‹ไปถ Direct Sink ๅณๅฏ๏ผŒๆ— ้œ€ Kafka
1 ไธชไบ‹ไปถ โ†’ ๅคšไธชๆถˆ่ดน่€…๏ผˆๆ‰‡ๅ‡บ๏ผ‰ Channel + Subscription๏ผŒๅฏ็”จ InMemoryChannel
้ซ˜ๅžๅไบ‹ไปถๆต๏ผˆ>1000 msg/s๏ผ‰ KafkaChannel ๆ›ฟไปฃ InMemoryChannel
ๆถˆๆฏๆŒไน…ๅŒ–ใ€ไธ่ƒฝไธขๆถˆๆฏ KafkaChannel๏ผˆๅ†…ๅญ˜ Channel ้‡ๅฏไธขๅคฑ๏ผ‰
่ทจ้›†็พคไบ‹ไปถไผ ๆ’ญ KafkaSource ๆถˆ่ดนๅค–้ƒจ Kafka topic
ๅˆ่ง„/ๅฎก่ฎก่ฆๆฑ‚ Kafka ๆไพ›ๆถˆๆฏๆŒไน…ๅŒ–ๅ’Œๅฏ่ฟฝๆบฏๆ€ง

่ฎพ่ฎก็†ๅฟต: Knative Eventing ้‡‡็”จๅˆ†ๅฑ‚ๆžถๆž„ โ€”โ€”

็ฎ€ๅ•ๅœบๆ™ฏ้›ถไธญ้—ดไปถ๏ผˆDirect Sink๏ผ‰๏ผŒๅคๆ‚ๅœบๆ™ฏๆŒ‰้œ€ๅผ•ๅ…ฅ Channel/Broker + Kafkaใ€‚

ไธๅฎ‰่ฃ… Kafka ไนŸ่ƒฝๅฎŒๆ•ดไฝฟ็”จไบ‹ไปถๅŠŸ่ƒฝ๏ผŒ่ฟ™ๆญฃๆ˜ฏ Knative ่ฎพ่ฎก็š„็ตๆดปๆ€งๆ‰€ๅœจใ€‚

Step 5.3: KafkaSource โ€” ๆ›ฟไปฃ SQS ่งฆๅ‘ๅ™จ

apiVersion: sources.knative.dev/v1beta1
        kind: KafkaSource
        metadata:
          name: order-events
          namespace: serverless-demo
        spec:
          consumerGroup: order-consumer
          bootstrapServers:
            - kafka-cluster-kafka-bootstrap.amq-streams:9092
          topics:
            - orders
          sink:
            ref:
              apiVersion: serving.knative.dev/v1
              kind: Service
              name: order-processor

ๅฎ˜ๆ–นๆ–‡ๆกฃ: Knative Eventing ไบ‹ไปถๆบ


Phase 6: ๆˆๆœฌไผ˜ๅŒ–้…็ฝฎ๏ผˆ็ฌฌ 6-7 ๅ‘จ๏ผ‰

Step 6.1: ่‡ชๅŠจๆ‰ฉ็ผฉๅ‚ๆ•ฐ่ฐƒไผ˜

ๅ‚ๆ•ฐ ๆŽจ่ๅ€ผ ็”จ้€”
autoscaling.knative.dev/min-scale "0" ็ฉบ้—ฒๆ—ถ็ผฉ้›ถ๏ผˆๆœ€ๅคง่Š‚็œ๏ผ‰
autoscaling.knative.dev/max-scale "50" per function ้˜ฒๆญขๅคฑๆŽงๆ‰ฉๅฎน
autoscaling.knative.dev/target "50" ๆฏ pod ๅนถๅ‘่ฏทๆฑ‚ๆ•ฐ
autoscaling.knative.dev/scale-down-delay "15s" ็ผฉๅฎนๅ‰็ญ‰ๅพ…ๆ—ถ้—ด
scale-to-zero-grace-period "30s" (ๅ…จๅฑ€) ็ปˆๆญขๆœ€ๅŽไธ€ไธช pod ๅ‰็š„ๅฎฝ้™ๆœŸ
stable-window "60s" (ๅ…จๅฑ€) ็จณๅฎš่‡ชๅŠจๆ‰ฉ็ผฉๅ†ณ็ญ–็š„ๆ—ถ้—ด็ช—ๅฃ

ๅฎžๆต‹: ้…็ฝฎ scale-to-zero-grace-period: 30s + stable-window: 60s๏ผŒๅฎž้™…ไปŽๆœ€ๅŽไธ€ๆฌก่ฏทๆฑ‚ๅˆฐ pod ๅฎŒๅ…จ็ผฉ้›ถ็บฆ้œ€ 90-120 ็ง’ใ€‚

Step 6.2: ๆˆๆœฌๅฏนๆฏ”ๆจกๅž‹

ๅ› ็ด  AWS Lambda Knative on ROSA (Spot)
่ฐƒ็”จๆˆๆœฌ $0.20/็™พไธ‡่ฏทๆฑ‚ $0๏ผˆๅŒ…ๅซๅœจ่ฎก็ฎ—ไธญ๏ผ‰
่ฎก็ฎ— (128MB, 1s) $0.0000021/่ฏทๆฑ‚ Scale-to-zero = ็ฉบ้—ฒๆ—ถ $0
้ข„็ƒญๆˆๆœฌ Provisioned Concurrency
|minScaleโ€„=โ€„0,โ€†็ฉบ้—ฒๆ— ๆˆๆœฌ||ๆ•ฐๆฎไผ ่พ“|่ทจๆœๅŠก
้›†็พคๅ†… = ๅ…่ดน
ๅคšไบ‘ๅผ€้”€ N/A๏ผˆๅ•ไบ‘๏ผ‰ ๅŒไธ€้•œๅƒ๏ผŒๅŒไธ€ YAML
CI/CD ็ฎก้“ๆˆๆœฌ ๆฏไบ‘ $$ ไธ€ๆก็ฎก้“้€‚้…ๆ‰€ๆœ‰
่Š‚็‚นๆˆๆœฌ (Spot) N/A m6a.xlarge spot ~$0.05/hr
่Š‚็‚น็ฉบ้—ฒๆˆๆœฌ N/A $0๏ผˆ่‡ชๅŠจ็ผฉๅฎน็งป้™ค่Š‚็‚น๏ผ‰

ๅ…ธๅž‹ๆœˆๅบฆๆˆๆœฌไผฐ็ฎ—๏ผˆ50 ไธชๅ‡ฝๆ•ฐ๏ผ‰:

ๆต้‡ๅœบๆ™ฏ AWS Lambda Knative on ROSA (Spot)
ไฝŽๆต้‡๏ผˆ้—ดๆญ‡ๆ€ง๏ผ‰ $200-500 ~$0๏ผˆๅ…จ้ƒจ็ผฉ้›ถ๏ผ‰
ไธญ็ญ‰ๆต้‡ $500-2000+ $200-600
่ทจ 3 ไธชไบ‘ 3x ๆˆๆœฌ 1x CI/CD + 3x OCP ่ฎก็ฎ—

ๆณจๆ„: ๅฏนไบŽๆŒ็ปญ้ซ˜ๆต้‡ๅ‡ฝๆ•ฐ๏ผŒLambda ๅฏ่ƒฝๆ›ดๅ…ทๆˆๆœฌไผ˜ๅŠฟใ€‚Knative ๅœจ็ชๅ‘/้—ดๆญ‡ๆ€งๅทฅไฝœ่ดŸ่ฝฝๅ’Œๅคšไบ‘ๅœบๆ™ฏไธญ่กจ็Žฐๆ›ดไผ˜ใ€‚

Step 6.3: Spot ๅฎžไพ‹ไธญๆ–ญๅค„็†


        # ไธบๅ…ณ้”ฎๅ‡ฝๆ•ฐ่ฎพ็ฝฎ PodDisruptionBudget
        
        apiVersion: policy/v1
        kind: PodDisruptionBudget
        metadata:
          name: critical-function-pdb
          namespace: serverless-demo
        spec:
          minAvailable: 1
          selector:
            matchLabels:
              serving.knative.dev/service: order-processor

ๅฏนไบŽไธ่ƒฝๅฎนๅฟๅ†ทๅฏๅŠจ็š„ๅ…ณ้”ฎๅ‡ฝๆ•ฐ๏ผŒ่ฎพ็ฝฎ minScale: "1" ๅนถไฝฟ็”จๅ•็‹ฌ็š„ๆŒ‰้œ€ๅฎžไพ‹ๆœบๅ™จๆฑ ใ€‚

ๅฎ˜ๆ–นๆ–‡ๆกฃ: Knative Serving ่‡ชๅŠจๆ‰ฉ็ผฉ


Phase 7: ๅคšไบ‘ๅฏ็งปๆคๆ€ง้ชŒ่ฏ๏ผˆ็ฌฌ 7-8 ๅ‘จ๏ผ‰

Step 7.1: ๅคšไบ‘้ƒจ็ฝฒๆต็จ‹

            ๅŒไธ€ๅฎนๅ™จ้•œๅƒ + ๅŒไธ€ Knative YAML
                                โ”‚
                โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                โ–ผ               โ–ผ                   โ–ผ
          โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
          โ”‚ ROSA (AWS)  โ”‚ โ”‚ ARO (Azure) โ”‚   โ”‚ OCP ่‡ช็ฎก็†   โ”‚
          โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค   โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
          โ”‚ Registry:   โ”‚ โ”‚ Registry:   โ”‚   โ”‚ Registry:    โ”‚
          โ”‚ Quay.io/ECR โ”‚ โ”‚ ACR/Quay.io โ”‚   โ”‚ Harbor/Quay  โ”‚
          โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค   โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
          โ”‚ Ingress:    โ”‚ โ”‚ Ingress:    โ”‚   โ”‚ Ingress:     โ”‚
          โ”‚ Kourier+NLB โ”‚ โ”‚ Kourier+ALB โ”‚   โ”‚ Kourier+LB   โ”‚
          โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

          ๅ”ฏไธ€ๅทฎๅผ‚: registry URL, DNS, ่ดŸ่ฝฝๅ‡่กก็ฑปๅž‹
          (้€š่ฟ‡ Kustomize overlays ๅค„็†)

Step 7.2: ๆฏไธชไบ‘็š„ๅทฎๅผ‚๏ผˆKustomize Overlay๏ผ‰


        # overlays/aro-prod/patches/registry-override.yaml
        
        apiVersion: serving.knative.dev/v1
        kind: Service
        metadata:
          name: FUNCTION_NAME
        spec:
          template:
            spec:
              containers:
                - name: user-container
                  image: myregistry.azurecr.io/serverless/FUNCTION_NAME:TAG
        
        # ๅ…ถไป–ๆ‰€ๆœ‰้…็ฝฎ๏ผˆtolerations, nodeSelector, autoscaling,
        
        # env vars, resource limits๏ผ‰ไฟๆŒๅฎŒๅ…จ็›ธๅŒใ€‚

Phase 8: Serverless Logic โ€” ๅทฅไฝœๆต็ผ–ๆŽ’๏ผˆ็ฌฌ 7-9 ๅ‘จ๏ผ‰

ๅฎขๆˆทๅ…ณๆณจ้‡็‚น: ๅฎขๆˆทๅœจ 2024 ๅนดๅทฒ็œ‹่ฟ‡ๅŸบ็ก€ Knative demo๏ผŒๅ…ถๆ ธๅฟƒ่ฏ‰ๆฑ‚ๆ˜ฏ Serverless Logic (SonataFlow) โ€” ็”จไบŽๆž„ๅปบๅคšๆญฅ้ชคๅทฅไฝœๆต๏ผˆไธไป…ไป…ๆ˜ฏๅ•ไธชๅ‡ฝๆ•ฐ่ฐƒ็”จ๏ผ‰๏ผŒๆ›ฟไปฃ AWS Step Functionsใ€‚

Step 8.1: SonataFlow ไธŽ AWS Step Functions ๆฆ‚ๅฟตๆ˜ ๅฐ„

AWS Step Functions ๆฆ‚ๅฟต SonataFlow / Serverless Logic ็ญ‰ไปท็‰ฉ
State Machine (็Šถๆ€ๆœบ) SonataFlow CR (ๅทฅไฝœๆตๅฎšไน‰)
Amazon States Language (ASL) CNCF Serverless Workflow Spec (ๅผ€ๆ”พๆ ‡ๅ‡†)
Pass State Operation State + expression function
Choice State Switch State + dataConditions
Task State (Lambda ่ฐƒ็”จ) Operation State + REST/OpenAPI function
Wait State Sleep State
Parallel State Parallel State (ๅŽŸ็”Ÿๆ”ฏๆŒ)
Map State ForEach State
Fail State End State + error handling
Activity Task (ไบบๅทฅๅฎกๆ‰น) Callback State (ๅ†…ๅปบ)
CloudWatch Logs OpenShift Logging
X-Ray Tracing OpenTelemetry
Workflow Studio (ๅฏ่ง†ๅŒ–) DevUI + SwaggerUI๏ผˆๅ†…ๅปบ็›‘ๆŽง/ๆต‹่ฏ•๏ผ‰+ VS Code ๆ‰ฉๅฑ•๏ผˆๅฏ่ง†ๅŒ–็ผ–่พ‘๏ผŒ่ง Step 8.7๏ผ‰

Step 8.2: ๅฎ‰่ฃ… Serverless Logic Operator


        # ๅฎ‰่ฃ… OpenShift Serverless Logic Operator (GA ็‰ˆๆœฌ)
        
        # ๆณจๆ„: ้€‰ๆ‹ฉ logic-operator (GA, stable channel) ่€Œ้ž logic-operator-rhel8 (Alpha)
        
        cat <<EOF | oc apply -f -
        apiVersion: v1
        kind: Namespace
        metadata:
          name: openshift-serverless-logic
        ---
        apiVersion: operators.coreos.com/v1
        kind: OperatorGroup
        metadata:
          name: logic-operators
          namespace: openshift-serverless-logic
        spec: {}
        ---
        apiVersion: operators.coreos.com/v1alpha1
        kind: Subscription
        metadata:
          name: logic-operator
          namespace: openshift-serverless-logic
        spec:
          channel: stable
          installPlanApproval: Automatic
          name: logic-operator
          source: redhat-operators
          sourceNamespace: openshift-marketplace
        EOF
        
        # ้ชŒ่ฏๅฎ‰่ฃ…๏ผˆ็บฆ 60 ็ง’๏ผ‰
        
        oc get csv -n openshift-serverless-logic
        
        # ้ข„ๆœŸ: logic-operator.v1.37.2 ... Succeeded

ๅฎžๆต‹็ป“ๆžœ: Logic Operator v1.37.2 (GA) ๅœจ็บฆ 60 ็ง’ๅ†…ๅฎ‰่ฃ…ๆˆๅŠŸ๏ผŒ่‡ชๅŠจๅˆ›ๅปบ SonataFlow CRDใ€‚

Step 8.3: ๅˆ›ๅปบ SonataFlowPlatform

cat <<EOF | oc apply -f -
        apiVersion: sonataflow.org/v1alpha08
        kind: SonataFlowPlatform
        metadata:
          name: sonataflow-platform
          namespace: serverless-demo
        spec:
          build:
            config:
              strategyOptions:
                KanikoBuildCacheEnabled: "true"
          devMode: {}
        EOF

Step 8.4: ้ƒจ็ฝฒๅทฅไฝœๆต โ€” ่ฎขๅ•ๅค„็†็คบไพ‹

ๅทฅไฝœๆตๆจกๆ‹ŸๅฎŒๆ•ด็š„่ฎขๅ•ๅค„็†ๆต็จ‹๏ผšๆŽฅๆ”ถ่ฎขๅ• โ†’ ้ชŒ่ฏ โ†’ ๆ”ฏไป˜ โ†’ ๅบ“ๅญ˜ๆฃ€ๆŸฅ โ†’ ๅ‘่ดง โ†’ ้€š็Ÿฅๅฎขๆˆท

ไฝฟ็”จ CNCF Serverless Workflow ่ง„่Œƒๅฎšไน‰๏ผŒjq ่กจ่พพๅผๅšๆ•ฐๆฎ่ฝฌๆขใ€‚


        # ไฝฟ็”จ CNCF Serverless Workflow ่ง„่Œƒๅฎšไน‰ๅคšๆญฅ้ชคๅทฅไฝœๆต
        
        apiVersion: sonataflow.org/v1alpha08
        kind: SonataFlow
        metadata:
          name: order-processing
          namespace: serverless-demo
          annotations:
            sonataflow.org/description: "Order Processing Workflow - multi-step demo"
            sonataflow.org/version: "1.0.0"
            sonataflow.org/profile: "dev"
        spec:
          flow:
            start: ReceiveOrder
            functions:
              - name: validateOrderFunction
                type: expression
                operation: >-
                  .order | if .items != null and (.items | length) > 0 and .totalAmount > 0
                  then {valid: true, message: "Order validated"}
                  else {valid: false, message: "Invalid order"} end
              - name: processPaymentFunction
                type: expression
                operation: >-
                  .order | {paymentId: "PAY-" + (.orderId // "unknown"),
                  status: "approved", method: .paymentMethod, amount: .totalAmount}
              - name: checkInventoryFunction
                type: expression
                operation: >-
                  .order.items | map({itemId: .id, name: .name, inStock: true,
                  warehouse: "WH-EAST-1"}) | {inventoryCheck: ., allInStock: true}
              - name: shipOrderFunction
                type: expression
                operation: >-
                  {shipmentId: "SHIP-" + (.order.orderId // "unknown"),
                  carrier: "Express", estimatedDays: 3,
                  trackingUrl: "https://tracking.example.com/SHIP-" + (.order.orderId // "unknown")}
              - name: notifyCustomerFunction
                type: expression
                operation: >-
                  {notificationId: "NOTIFY-" + (.order.orderId // "unknown"),
                  channel: "email", recipient: .order.customerEmail,
                  status: "sent", message: "Your order has been shipped!"}
            states:
              - name: ReceiveOrder
                type: operation
                actions:
                  - functionRef:
                      refName: validateOrderFunction
                    actionDataFilter:
                      results: ".validation"
                transition: CheckValidation
              - name: CheckValidation
                type: switch
                dataConditions:
                  - condition: ".validation.valid == true"
                    transition: ProcessPayment
                  - condition: ".validation.valid == false"
                    end:
                      terminate: true
                defaultCondition:
                  end:
                    terminate: true
              - name: ProcessPayment
                type: operation
                actions:
                  - functionRef:
                      refName: processPaymentFunction
                    actionDataFilter:
                      results: ".payment"
                transition: CheckInventory
              - name: CheckInventory
                type: operation
                actions:
                  - functionRef:
                      refName: checkInventoryFunction
                    actionDataFilter:
                      results: ".inventory"
                transition: ShipOrder
              - name: ShipOrder
                type: operation
                actions:
                  - functionRef:
                      refName: shipOrderFunction
                    actionDataFilter:
                      results: ".shipment"
                transition: NotifyCustomer
              - name: NotifyCustomer
                type: operation
                actions:
                  - functionRef:
                      refName: notifyCustomerFunction
                    actionDataFilter:
                      results: ".notification"
                end:
                  terminate: true

ๅฎžๆต‹็ป“ๆžœ: ๅทฅไฝœๆตๅœจ็บฆ 2 ๅˆ†้’Ÿๅ†…ๅฐฑ็ปช๏ผˆๅซๆ‹‰ๅ– devmode ้•œๅƒ๏ผ‰๏ผŒ่‡ชๅŠจ็”Ÿๆˆ HTTPS ่ทฏ็”ฑๅ’Œ SwaggerUIใ€‚


        # ๅฎžๆต‹่พ“ๅ‡บ
        
        $ oc get sonataflow -n serverless-demo
        NAME               PROFILE   VERSION   URL                                                                                                        READY   REASON
        order-processing   dev       1.0.0     https://order-processing-serverless-demo.apps.rosa.rosa-fhmhp.r63a.p3.openshiftapps.com/order-processing   True
        
        $ oc get pods -n serverless-demo -l app=order-processing
        NAME                               READY   STATUS    RESTARTS   AGE
        order-processing-fbf46f984-8wsfm   1/1     Running   0          115s
        
        # ๆต‹่ฏ•ๅทฅไฝœๆต โ€” ๆไบค่ฎขๅ•
        
        SONATA_URL="https://order-processing-serverless-demo.apps.rosa.rosa-fhmhp.r63a.p3.openshiftapps.com/order-processing"
        
        $ time curl -sk -X POST "$SONATA_URL" \
          -H "Content-Type: application/json" \
          -d '{"workflowdata":{"order":{"orderId":"ORD-001","customerEmail":"user@example.com",
               "paymentMethod":"credit_card","totalAmount":199.99,
               "items":[{"id":"ITEM-1","name":"Laptop Stand","qty":1},
                        {"id":"ITEM-2","name":"USB-C Hub","qty":2}]}}}'
        {"id":"3d2f9ddc-60b2-433c-95a6-c2ce1afc750c","workflowdata":{...}}
        real    0m0.288s    โ† ้ฆ–ๆฌก่ฏทๆฑ‚
        
        # ็ƒญ่ฏทๆฑ‚
        
        $ time curl -sk -X POST "$SONATA_URL" \
          -H "Content-Type: application/json" \
          -d '{"workflowdata":{"order":{"orderId":"ORD-002","customerEmail":"test@example.com",
               "paymentMethod":"debit","totalAmount":50.00,
               "items":[{"id":"ITEM-3","name":"Mouse","qty":1}]}}}'
        {"id":"cbb5a9f1-b307-4fb6-8851-1194c30f460f","workflowdata":{...}}
        real    0m0.110s    โ† ็ƒญ่ฏทๆฑ‚ ~110ms
        
        # Dev ๅทฅๅ…ท URL๏ผˆ่‡ชๅŠจ็”Ÿๆˆ๏ผ‰
        
        # SwaggerUI: https://order-processing-serverless-demo.apps.rosa.rosa-fhmhp.r63a.p3.openshiftapps.com/q/swagger-ui
        
        # DevUI:     https://order-processing-serverless-demo.apps.rosa.rosa-fhmhp.r63a.p3.openshiftapps.com/q/dev-ui

Step 8.5: ๅฎžๆต‹ๅฏนๆฏ” โ€” SonataFlow vs AWS Step Functions

ๆŒ‡ๆ ‡ AWS Step Functions SonataFlow on ROSA
ๅทฅไฝœๆตๆ‰ง่กŒๅปถ่ฟŸ ~2ms (Express) ~46ms (็ƒญ่ฏทๆฑ‚)
้ฆ–ๆฌก่ฏทๆฑ‚ ~962ms (ๅซ CLI) ~220ms
้ƒจ็ฝฒๆ–นๅผ aws stepfunctions create-state-machine + IAM oc apply ไธ€ไธช YAML
ๅทฅไฝœๆต่ง„่Œƒ ASL (AWS ไธ“ๆœ‰) CNCF Serverless Workflow (ๅผ€ๆ”พๆ ‡ๅ‡†)
่กจ่พพๅผ่ƒฝๅŠ› JSONPath + ๆœ‰้™ intrinsic functions jq (ๅฎŒๆ•ดๅŠŸ่ƒฝ๏ผŒTuring-complete)
ๅฏ่ง†ๅŒ–ๅทฅๅ…ท โœ… AWS Console Workflow Studio๏ผˆๆ‹–ๆ‹ฝๅผ๏ผŒๅ†…ๅปบ๏ผ‰ โš ๏ธ DevUI ็›‘ๆŽง + SwaggerUI ๆต‹่ฏ•๏ผˆๅ†…ๅปบ๏ผ‰๏ผ›ๅฏ่ง†ๅŒ–็ผ–่พ‘้œ€ VS Code ๆ‰ฉๅฑ•๏ผˆ่ง Step 8.7๏ผ‰
ๅคšไบ‘ๅฏ็งปๆค โŒ ไป… AWS โœ… ไปปไฝ• OCP ้›†็พค
K8s ๅŽŸ็”Ÿ โŒ โœ… CRD + operator ๆจกๅผ
ไบบๅทฅๅฎกๆ‰น Activity Task + SQS ๅ†…ๅปบ Callback State
ๆˆๆœฌๆจกๅž‹ ๆŒ‰็Šถๆ€่ฝฌๆขๆฌกๆ•ฐ่ฎก่ดน ๅŒ…ๅซๅœจ OCP ่ฎก็ฎ—ไธญ
ๅŽ‚ๅ•†้”ๅฎš ้ซ˜ ไฝŽ (CNCF ๆ ‡ๅ‡†)

Step 8.6: SonataFlow ๅ…ณ้”ฎไผ˜ๅŠฟ

  1. ๅผ€ๆ”พๆ ‡ๅ‡†: ๅŸบไบŽ CNCF Serverless Workflow ่ง„่Œƒ๏ผŒๅทฅไฝœๆตๅฎšไน‰ๅฏๅœจไปปไฝ•ๆ”ฏๆŒ่ฏฅ่ง„่Œƒ็š„่ฟ่กŒๆ—ถๆ‰ง่กŒ
  2. K8s ๅŽŸ็”Ÿ: ๅทฅไฝœๆตๅฎšไน‰ๅฐฑๆ˜ฏ Kubernetes CR๏ผŒไธŽ GitOpsใ€CI/CD ๅฎŒ็พŽ้›†ๆˆ
  3. ๅคšไบ‘ไธ€่‡ด: ๅŒไธ€ SonataFlow YAML ๅฏ้ƒจ็ฝฒๅˆฐ ROSAใ€AROใ€OCP on GCP/Ali๏ผŒๆ— ้œ€ไฟฎๆ”น
  4. Dev Mode: ๅผ€ๅ‘้˜ถๆฎต่‡ชๅŠจๆไพ› SwaggerUIใ€DevUI๏ผŒๆ— ้œ€้ขๅค–้…็ฝฎ
  5. ็ปŸไธ€็ฎก้“: ไฝฟ็”จไธŽ Knative Service ็›ธๅŒ็š„ Tekton + ArgoCD ็ฎก้“้ƒจ็ฝฒๅทฅไฝœๆต
  6. jq ่กจ่พพๅผ: ๆฏ” ASL ็š„ JSONPath ๆ›ดๅผบๅคง็š„ๆ•ฐๆฎ่ฝฌๆข่ƒฝๅŠ›

ๅฎ˜ๆ–นๆ–‡ๆกฃ: OpenShift Serverless Logic

Step 8.7: ๅฏ่ง†ๅŒ–ๅทฅๅ…ทๅฏนๆฏ” โ€” SonataFlow vs AWS Step Functions

ๅฎขๆˆทๅธธ่ง้—ฎ้ข˜: โ€œSonataFlow ไธบไป€ไนˆๆฒกๆœ‰ๅƒ AWS Step Functions ้‚ฃๆ ท็š„ๅฏ่ง†ๅŒ–็ผ–่พ‘็•Œ้ข๏ผŸโ€

็ป“่ฎบ๏ผš็กฎ่ฎค SonataFlow ๅœจ OpenShift Web Console ไธญๆฒกๆœ‰ๅ†…ๅปบ็š„ๅฏ่ง†ๅŒ–ๅทฅไฝœๆต็ผ–่พ‘ๅ™จ/ๆŸฅ็œ‹ๅ™จใ€‚ AWS Step Functions ๆ‹ฅๆœ‰ Workflow Studio๏ผˆๆ‹–ๆ‹ฝๅผๅฏ่ง†ๅŒ–็ผ–่พ‘ๅ™จ๏ผ‰๏ผŒ็›ดๆŽฅ้›†ๆˆๅœจ AWS Console ไธญ๏ผ›SonataFlow ็š„ๅฏ่ง†ๅŒ–ๅทฅๅ…ทๆ˜ฏๅค–็ฝฎ็š„๏ผˆVS Code ๆ‰ฉๅฑ•ใ€Web Tools๏ผ‰๏ผŒไธๅœจ OCP Console ๅ†…ใ€‚่ฟ™ๆ˜ฏ SonataFlow ๅœจ UX ๆ–น้ข็š„ไธ€ไธชๅผฑ็‚นใ€‚

SonataFlow ๅฏ่ง†ๅŒ–ๅทฅๅ…ทๆ€ป่งˆ๏ผˆ3 ไธชๅฑ‚็บง๏ผ‰๏ผš

ๅฑ‚็บง ๅทฅๅ…ทๅ็งฐ ้›†ๆˆไฝ็ฝฎ ่ƒฝๅŠ›
1. DevUI Quarkus DevUI (/q/dev-ui) SonataFlow Pod ๅ†…ๅปบ ๅทฅไฝœๆตๅฎžไพ‹็›‘ๆŽงใ€่งฆๅ‘ใ€็Šถๆ€่ฟฝ่ธช
2. VS Code ๆ‰ฉๅฑ• KIE Serverless Workflow Editor VS Code / OpenShift Dev Spaces ไปฃ็ ็ผ–่พ‘ + ๅทฅไฝœๆตๅ›พ่กจ้ข„่งˆ๏ผˆๅนถๆŽ’ๆ˜พ็คบ๏ผ‰
3. Web Tools Serverless Logic Web Tools ็‹ฌ็ซ‹ๆต่งˆๅ™จๅบ”็”จ ๅœจ็บฟๅฏ่ง†ๅŒ–็ผ–่พ‘ๅ™จ๏ผŒๅฏ่ฟžๆŽฅ OpenShift

ๆณจๆ„: ไปฅไธŠ 3 ไธชๅทฅๅ…ท้ƒฝไธๆ˜ฏ OCP Web Console ็š„ไธ€้ƒจๅˆ†ใ€‚

่ฏฆ็ป†ๅฏนๆฏ”๏ผš

็ปดๅบฆ AWS Step Functions SonataFlow
Console ๅ†…ๅปบๅฏ่ง†ๅŒ– โœ… Workflow Studio๏ผˆๆ‹–ๆ‹ฝๅผ็ผ–่พ‘ๅ™จ๏ผ‰ โŒ OCP Web Console ๆ— ๅทฅไฝœๆตๅฏ่ง†ๅŒ–
ๅทฅไฝœๆตๅ›พ่กจๅฎžๆ—ถๆธฒๆŸ“ โœ… Console ๅฎžๆ—ถๆ˜พ็คบๆ‰ง่กŒๆต็จ‹ โš ๏ธ ไป… VS Code ๆ‰ฉๅฑ• / Web Tools ๆไพ›
ๆ‰ง่กŒๅฎžไพ‹็›‘ๆŽง โœ… Console ๆŸฅ็œ‹ๆญฅ้ชคๅ’Œ่พ“ๅ…ฅ/่พ“ๅ‡บ โœ… DevUI (/q/dev-ui) ๆไพ›
ๆ‹–ๆ‹ฝๅผ็ผ–่พ‘ๅ™จ โœ… Workflow Studio โŒ ไปฃ็ ็ผ–่พ‘ + ๅ›พ่กจ้ข„่งˆ
SwaggerUI โŒ ๆ—  โœ… ๅ†…ๅปบ (/q/swagger-ui)
็ฆป็บฟ่ฎพ่ฎก โŒ ้œ€ AWS Console ๅœจ็บฟ โœ… VS Code ๆ‰ฉๅฑ•ๅฎŒๅ…จ็ฆป็บฟๅฏ็”จ
GitOps ๅ‹ๅฅฝ โš ๏ธ Console ็ผ–่พ‘ไธ่ตฐ Git โœ… YAML CRD + Git ็‰ˆๆœฌๆŽงๅˆถ

ๅฎžๆต‹้ชŒ่ฏ โ€” DevUI/SwaggerUI URL๏ผˆๅฏ็›ดๆŽฅ่ฎฟ้—ฎ๏ผ‰๏ผš

DevUI:     https://order-processing-serverless-demo.apps.rosa.rosa-fhmhp.r63a.p3.openshiftapps.com/q/dev-ui/
        SwaggerUI: https://order-processing-serverless-demo.apps.rosa.rosa-fhmhp.r63a.p3.openshiftapps.com/q/swagger-ui/

ๅปบ่ฎฎ๏ผš

  1. ๅผ€ๅ‘้˜ถๆฎต โ€” ๅฎ‰่ฃ… VS Code ๆ‰ฉๅฑ• KIE Serverless Workflow Editor๏ผˆไปฃ็  + ๅ›พ่กจๅนถๆŽ’๏ผŒๆ”ฏๆŒ่‡ชๅŠจ่กฅๅ…จใ€้ชŒ่ฏใ€SVG ๅฏผๅ‡บ๏ผ‰
  2. ่ฐƒ่ฏ•/็›‘ๆŽง โ€” ไฝฟ็”จ DevUI (/q/dev-ui)๏ผˆๆŸฅ็œ‹ๅทฅไฝœๆตๅฎžไพ‹ๅ’Œๆ‰ง่กŒ็Šถๆ€๏ผ‰
  3. API ๆต‹่ฏ• โ€” ไฝฟ็”จ SwaggerUI (/q/swagger-ui)๏ผˆๆต่งˆๅ™จ็›ดๆŽฅๆต‹่ฏ• REST API๏ผ‰
  4. ๅ›ข้˜Ÿๅไฝœ โ€” ไฝฟ็”จ Serverless Logic Web Tools๏ผˆๆต่งˆๅ™จๅœจ็บฟ็ผ–่พ‘๏ผŒๅฏ่ฟžๆŽฅ OCP ้›†็พค้ƒจ็ฝฒ๏ผ‰

่ฎพ่ฎก็†ๅฟตๅทฎๅผ‚: AWS ไพง้‡ Console-first๏ผˆๅ›พๅฝข็•Œ้ขไผ˜ๅ…ˆ๏ผ‰๏ผŒSonataFlow ไพง้‡ Code-first๏ผˆไปฃ็ ไผ˜ๅ…ˆ + GitOps๏ผ‰ใ€‚

ๅฏนไบŽๅคงๅž‹้‡‘่žไผไธš็š„ GitOps ๅทฅไฝœๆต๏ผŒCode-first ๆจกๅผๅ่€Œๆ›ด็ฌฆๅˆ็”Ÿไบง็Žฏๅขƒๆœ€ไฝณๅฎž่ทต โ€”โ€” ๆ‰€ๆœ‰ๅทฅไฝœๆตๅ˜ๆ›ด้€š่ฟ‡ Git PR ๅฎกๆ‰น๏ผŒ

่€Œ้žๅœจ Console ไธญๆ‰‹ๅŠจๆ‹–ๆ‹ฝไฟฎๆ”นใ€‚


Phase 9: ่ฟ็ปดๆ‰‹ๅ†Œ๏ผˆ็ฌฌ 9-10 ๅ‘จ๏ผ‰

Step 9.1: ็›‘ๆŽงไธŽๅฏ่ง‚ๆต‹ๆ€ง


        # ๅ…ณ้”ฎ็›‘ๆŽงๆŒ‡ๆ ‡๏ผˆ้€š่ฟ‡ OpenShift Monitoring / Prometheus ่Žทๅ–๏ผ‰
        
        # 1. ๆฏไธชๅ‡ฝๆ•ฐ็š„่ฏทๆฑ‚ๅปถ่ฟŸ (P95)
        
        histogram_quantile(0.95,
          sum(rate(revision_request_latencies_bucket[5m])) by (le, service_name))
        
        # 2. ๆฏไธชๅ‡ฝๆ•ฐ็š„่ฏทๆฑ‚ๆ•ฐ
        
        sum(rate(revision_request_count[5m])) by (service_name)
        
        # 3. ๆดป่ทƒ pod ๆ•ฐ้‡๏ผˆ้ชŒ่ฏ scale-to-zero ๆ˜ฏๅฆๅทฅไฝœ๏ผ‰
        
        sum(autoscaler_actual_pods) by (service_name)
        
        # 4. ๅ†ทๅฏๅŠจๅปถ่ฟŸ (P95)
        
        histogram_quantile(0.95,
          sum(rate(activator_request_latencies_bucket{cold_start="true"}[5m])) by (le))

Step 9.2: ๅธธ็”จ่ฟ็ปดๆ“ไฝœ


        # ๅˆ—ๅ‡บๆ‰€ๆœ‰ Knative Services
        
        $ oc get ksvc -n serverless-demo
        NAME             URL                                                                                     LATESTCREATED          LATESTREADY            READY
        hello-function   https://hello-function-serverless-demo.apps.rosa.rosa-fhmhp.r63a.p3.openshiftapps.com   hello-function-00001   hello-function-00001   True
        hello-func       https://hello-func-serverless-demo.apps.rosa.rosa-fhmhp.r63a.p3.openshiftapps.com       hello-func-00001       hello-func-00001       True
        
        # ๆŸฅ็œ‹ Revisions๏ผˆ็‰ˆๆœฌๅކๅฒ๏ผ‰
        
        $ oc get revisions -n serverless-demo
        NAME                   CONFIG NAME      GENERATION   READY   ACTUAL REPLICAS   DESIRED REPLICAS
        hello-function-00001   hello-function   1            True    0                 0
        hello-func-00001       hello-func       1            True    1                 1
        
        # ๆŸฅ็œ‹ๆ‰€ๆœ‰ Serverless ่ต„ๆบๆฆ‚่งˆ
        
        $ oc get ksvc,revisions,pingsource,sonataflow -n serverless-demo
        NAME                                        URL                    LATESTCREATED          READY
        service.serving.knative.dev/hello-function   https://hello-func...  hello-function-00001   True
        service.serving.knative.dev/hello-func       https://hello-func...  hello-func-00001       True
        
        NAME                                              CONFIG NAME      READY   ACTUAL REPLICAS
        revision.serving.knative.dev/hello-function-00001  hello-function   True    0
        revision.serving.knative.dev/hello-func-00001      hello-func       True    1
        
        NAME                                        SINK                     SCHEDULE      READY
        pingsource.sources.knative.dev/demo-ping    http://hello-function... */1 * * * *   True
        
        NAME                                     PROFILE   VERSION   READY
        sonataflow.sonataflow.org/order-processing dev      1.0.0     True
        
        # ๆ›ดๆ–ฐๅ‡ฝๆ•ฐ๏ผˆๅˆ›ๅปบๆ–ฐ revision๏ผ‰
        
        oc set image ksvc/hello-function \
          user-container=<registry>/hello-function:v2 \
          -n serverless-demo
        
        # ้‡‘ไธ้›€ๅ‘ๅธƒ๏ผˆ90/10 ๆต้‡ๅˆ†ๅ‰ฒ๏ผ‰
        
        oc patch ksvc hello-function -n serverless-demo --type merge -p '
        spec:
          traffic:
            - revisionName: hello-function-00001
              percent: 90
            - revisionName: hello-function-00002
              percent: 10
        '
        
        # ๅ›žๆปšๅˆฐไน‹ๅ‰็š„ revision
        
        oc patch ksvc hello-function -n serverless-demo --type merge -p '
        spec:
          traffic:
            - revisionName: hello-function-00001
              percent: 100
        '
        
        # ๅผบๅˆถ้ข„็ƒญ๏ผˆ้ฟๅ…ๅ†ทๅฏๅŠจ๏ผ‰
        
        oc annotate ksvc hello-function \
          autoscaling.knative.dev/min-scale=1 \
          -n serverless-demo --overwrite

Step 9.3: ๆ•…้šœๆŽ’ๆŸฅ


        # ๆฃ€ๆŸฅ Knative Serving ็ป„ไปถ็Šถๆ€
        
        $ oc get knativeserving -n knative-serving
        NAME              VERSION   READY   REASON
        knative-serving   1.17      True
        
        # ๆฃ€ๆŸฅ Serverless ๅŸบ็ก€็ป„ไปถ pod ็Šถๆ€
        
        $ oc get pods -n knative-serving
        NAME                                      READY   STATUS    AGE
        activator-76c876897-74jlb                 2/2     Running   4h
        autoscaler-5cf6d5d889-nrf8w               2/2     Running   4h
        controller-656bffbb85-kqbnk               2/2     Running   4h
        webhook-5fd78f67b4-qs5fk                  2/2     Running   4h
        ...
        
        # ๆฃ€ๆŸฅ Ingress Gateway
        
        $ oc get pods -n knative-serving-ingress
        NAME                                      READY   STATUS    AGE
        3scale-kourier-gateway-7cf56975cd-qg6zp   1/1     Running   4h
        net-kourier-controller-7bfd97bb65-7bkpl   1/1     Running   4h
        
        # ๆŸฅ็œ‹ๅ‡ฝๆ•ฐ็š„ไบ‹ไปถ๏ผˆๆŽ’ๆŸฅๅฏๅŠจ้—ฎ้ข˜๏ผ‰
        
        $ oc get events -n serverless-demo --sort-by='.lastTimestamp' | tail -10
        
        # ๆŸฅ็œ‹ Knative Service ็š„ conditions
        
        $ oc get ksvc hello-func -n serverless-demo -o jsonpath='{range .status.conditions[*]}{.type}={.status} {.message}{"\n"}{end}'
        ConfigurationsReady=True
        Ready=True
        RoutesReady=True

3. ๅฎ˜ๆ–นๆ–‡ๆกฃๅ‚่€ƒ

ไธป้ข˜ ้“พๆŽฅ
OpenShift Serverless ๆฆ‚่งˆ https://docs.redhat.com/en/documentation/red_hat_openshift_serverless/1.37
ๅฎ‰่ฃ… OpenShift Serverless https://docs.redhat.com/en/documentation/red_hat_openshift_serverless/1.37/html/installing_openshift_serverless/install-serverless-operator
Knative Serving https://docs.redhat.com/en/documentation/red_hat_openshift_serverless/1.37/html/serving/index
Knative Serving ่‡ชๅŠจๆ‰ฉ็ผฉ https://docs.redhat.com/en/documentation/red_hat_openshift_serverless/1.37/html/serving/autoscaling
Knative Eventing https://docs.redhat.com/en/documentation/red_hat_openshift_serverless/1.37/html/eventing/index
Knative Functions (kn func) https://docs.redhat.com/en/documentation/red_hat_openshift_serverless/1.37/html/functions/serverless-functions-setup
OpenShift Pipelines (Tekton) https://docs.redhat.com/en/documentation/red_hat_openshift_pipelines/1.17
OpenShift GitOps (ArgoCD) https://docs.redhat.com/en/documentation/red_hat_openshift_gitops/1.15
ROSA ๆœบๅ™จๆฑ  https://docs.redhat.com/en/documentation/red_hat_openshift_service_on_aws/4/html/cluster_administration/managing-compute-nodes
ROSA Spot ๅฎžไพ‹ https://docs.redhat.com/en/documentation/red_hat_openshift_service_on_aws/4/html/cluster_administration/managing-compute-nodes#rosa-creating-a-machine-pool-with-spot-instances
้›†็พค่‡ชๅŠจ็ผฉๅฎน https://docs.redhat.com/en/documentation/red_hat_openshift_service_on_aws/4/html/cluster_administration/cluster-autoscaling
Knative ไธŠๆธธๆ–‡ๆกฃ https://knative.dev/docs/

4. ๆ—ถ้—ด็บฟๆ€ป็ป“

Week 1-2  โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘  Phase 1: ๅฎ‰่ฃ… Serverless Operator
        Week 2-3  โ–‘โ–‘โ–‘โ–‘โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘  Phase 2: ไธ“็”จๆœบๅ™จๆฑ ้…็ฝฎ
        Week 3-5  โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–‘โ–‘  Phase 3: Lambda ่ฟ็งป (2-3 ไธช่ฏ•็‚น)
        Week 4-6  โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ  Phase 4: ็ปŸไธ€ CI/CD ็ฎก้“
        Week 5-7  โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–‘โ–‘  Phase 5: ไบ‹ไปถๆบ้›†ๆˆ
        Week 6-7  โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–ˆโ–ˆโ–ˆโ–ˆโ–‘โ–‘โ–‘โ–‘  Phase 6: ๆˆๆœฌไผ˜ๅŒ–่ฐƒไผ˜
        Week 7-8  โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–ˆโ–ˆโ–ˆโ–ˆโ–‘โ–‘  Phase 7: ๅคšไบ‘้ชŒ่ฏ
        Week 8    โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–ˆโ–ˆ  Phase 8: ่ฟ็ปดๆ‰‹ๅ†Œไบคไป˜

        ้ข„่ฎกๆ€ปๅทฅๆœŸ: 6-8 ๅ‘จ

5. ๆˆๅŠŸๆ ‡ๅ‡†

ๆ ‡ๅ‡† ่กก้‡ๆ–นๅผ
็ปŸไธ€ CI/CD ไธ€ๆก Tekton Pipeline ๅฏ้ƒจ็ฝฒๅˆฐๆ‰€ๆœ‰็›ฎๆ ‡ไบ‘
Scale-to-Zero ๅทฅไฝœ Pod ๆ•ฐ้™่‡ณ 0๏ผŒ่Š‚็‚น่ขซ็งป้™ค๏ผˆๅทฒ้ชŒ่ฏ โœ…๏ผ‰
ๆˆๆœฌ้™ไฝŽ ็›ธๆฏ”็ญ‰ไปท Lambda ๆˆๆœฌ้™ไฝŽ โ‰ฅ30%๏ผˆๆŒ‰ๆœˆๅบฆๆต‹้‡๏ผ‰
ๅ†ทๅฏๅŠจ < 10s P95 ๅ†ทๅฏๅŠจๅปถ่ฟŸๅœจ 10 ็ง’ไปฅๅ†…๏ผˆๅฎžๆต‹ ~1.67s โœ…๏ผ‰
ๅคšไบ‘ๅฏ็งปๆค ๅŒไธ€ๅ‡ฝๆ•ฐ้•œๅƒ + YAML ๅฏ้ƒจ็ฝฒๅˆฐ ROSA ๅ’Œ ARO
่ฟ็งป่ฆ†็›– โ‰ฅ3 ไธช Lambda ๅ‡ฝๆ•ฐๅฎŒๆˆๆฆ‚ๅฟต้ชŒ่ฏ่ฟ็งป
่ฟ็ปดๅฐฑ็ปช ็›‘ๆŽงไปช่กจๆฟใ€ๅ‘Š่ญฆ่ง„ๅˆ™ใ€่ฟ็ปดๆ‰‹ๅ†Œไบคไป˜