티스토리 뷰

728x90
반응형

서론

Knative는 Kubernetes 환경에서 동작하는 서버리스 클라우드 네이티브 애플리케이션(Severless CNA)을 배포, 실행, 관리하기 위한 오픈소스 소프트웨어이다. Knative의 구성 요소는 Kubernetes를 기반으로 구축되어 복잡한 세부 사항을 추상화하고 개발자가 비즈니스 개발에만 집중할 수 있도록 하여, 개발자의 생산성을 높일 수 있다.

또한 Knative는 Serverless Computing으로 요청이 있을 때만 코드를 실행하고, 요청이 많을 경우에는 그에 비례하는 자원을 동적으로 Scale In-Out 또는 Zero 상태까지 유지하도록 하여 사용률과 확장성을 극대화할 수 있으며, 인프라 비용을 효과적으로 절감할 수 있다.

Public Cloud의 대표적인 Serverless Computing 기술은 AWS Lambda, Azure Functions, Google Cloud Functions 등이 있다. 이와 같이 Public Cloud의 Managed Service로 Serverless Computing을 적용할 경우 Service Lock In 요소가 되기 때문에 이를 오픈소스로 개발한 Knative가 하나의 대안으로 떠오르고 있다.


Knative 구성 과정

Knative 구성 과정은 크게 다음과 같이 구분해 볼 수 있다.

1) Knative 아키텍처

2) Knative 구축

3) Knative Build

4) Knative Serving


Knative 아키텍처

Knative를 활용하면, 개발자가 개발이외에 고려해야 하는 Docker 이미지 관리, Registry 통합, 서비스 배포, 로드밸런싱 구성, 모니터링, 로깅, Scale Out, CI/CD와 같은 문제를 완벽하게 해소해 줄 수 있다.

Knative의 다양한 기능 중 핵심 기능이라고 볼 수 있는 Build - Serving - Event에 대해 알아보도록 하자.

1. Build (소스에서 이미지를 빌드하는 기능)

Knative Build는 Kubernetes 기능을 기반으로 표준화되고 이식 가능하며 재사용 가능한 컨테이너 이미지 빌드 방법을 제공한다. Build를 적용하면, 개발자가 코드를 레지스트리로 보내기 전에 컴파일하고 패키징하는 일관된 방법을 정의 할 수 있다.

Build를 활용하여 Git에서 소스코드를 Clone하고 Docker Image를 빌드하고, Tagging - Registry Push 등을 수행한다. 빌드가 완료된 결과를 기반으로 serving를 수행하게 된다.

Serverless가 아닌 일반 클라우드 환경을 예를 든다면, 이 Build 기능이 Jenkins의 CI 부분과 매칭되는 형태라고 볼 수 있다.

2. Serving (스냅 샷 및 Scale In-Out을 관리하고 처리하며, K8S 클러스터에 애플리케이션 배포)

Knative Serving 구성 요소를 사용하면 K8S 클러스터에 컨테이너 이미지로 애플리케이션을 배포 할 수 있다. 또한 배포 가능한 스냅 샷을 유지하고 라우팅 및 모든 네트워킹 상호 작용을 처리한다. 마지막으로 애플리케이션 배포를 위한 확장 (확장 및 축소)을 제공한다.
a. Service : 워크로드의 전체 수명주기를 자동으로 관리하고 Route 생성, Configuration 및 Revision 제어한다. 항상 최신 Revision 또는 고정 Revision으로 트래픽을 라우팅하도록 서비스를 정의 할 수 있다.
b. Route : 네트워크 엔드 포인트를 하나 이상의 Revision에 매핑한다.

c. Configuration : 배포에 대해 원하는 상태를 유지하도록 한다.
d. Revision : 워크로드에 대한 특정 시점의 스냅 샷이다.

이 과정이 Jenkins의 CD 부분과 매칭된다고 볼 수 있다.

3. Event (메시지 수신을 위한 이벤트 중심의 Pub/Sub 지원)

Event는 MQ를 사용하여 서비스간 결합도를 낮추는 개발 방법이다. 이를 이용하여 이기종 간의 솔루션 연계 및 독립적인 애플리케이션 개발 등을 지원한다.


Knative 구축

Knative는 크게 두가지 형태의 구성을 지원한다. 대표적인 Service Mesh인 Isitio와 함께 구성하는 방법과 Gloo와 함께 구성하는 방법이다.

Knative는 Istio의 Virtual Gateway 기능만 사용하기 때문에 Istio가 제공하는 CRD 수십가지를 모두 활용할 필요가 없다. 따라서 Istio를 Service Mesh로 사용하기 위해 기 구성되어 있는 경우에는 Istio를 사용하되 Serverless만을 위해 구축할 경우 Light Weight한 Gloo를 사용하여 Knative를 구축하는 것을 권고한다.

다만 Gloo는 Knative의 Event 컴포넌트를 지원하지 않는다. 이번 포스팅에서는 다소 익숙하지 않은 Gloo를 사용하여 Knative를 적용해 보도록 하자.

Gloo : https://docs.solo.io/gloo-edge/latest/installation/gateway/kubernetes/

1. glooctl 설치

curl -sL https://run.solo.io/gloo/install | sh
export PATH=$HOME/.gloo/bin:$PATH

먼저 Gloo 및 Knative를 설치하기 위한 glooctl을 설치한다.

> 버전 확인

[root@ip-192-168-114-198 ~]# glooctl version
Client: {"version":"1.5.14"}
Server: version undefined, could not find any version of gloo running
[root@ip-192-168-114-198 ~]# 

2. Installing on Kubernetes with glooctl

glooctl로 knative를 설치한다. 이때 Gloo와 Knative Serving이 함께 구성된다.

> glooctl install knative

[root@ip-192-168-114-198 ~]# glooctl install knative
installing Knative CRDs...
installing Knative...
Knative successfully installed!
Creating namespace gloo-system... Done.
Starting Gloo Edge installation...

Gloo Edge was successfully installed!
[root@ip-192-168-114-198 ~]# 

3. knative 구축 확인

> kubectl get all -n gloo-system

[root@ip-192-168-114-198 ~]# kubectl get all -n gloo-system
NAME                                          READY   STATUS    RESTARTS   AGE
pod/discovery-5dc96cbb4d-94fbn                1/1     Running   0          2m3s
pod/gloo-6d86dc87c8-hb58b                     1/1     Running   0          2m3s
pod/ingress-6f95fd7dc-bj65l                   1/1     Running   0          2m3s
pod/knative-external-proxy-f4f67644d-drzps    1/1     Running   0          2m3s
pod/knative-internal-proxy-7cd8448b58-qcfgs   1/1     Running   0          2m3s

NAME                             TYPE           CLUSTER-IP       EXTERNAL-IP                                                                    PORT(S)                               AGE
service/gloo                     ClusterIP      10.100.230.54    <none>                                                                         9977/TCP,9976/TCP,9988/TCP,9979/TCP   2m3s
service/knative-external-proxy   LoadBalancer   10.100.68.120    afe2c222e1558413d8e8acfd0ef74357-1341022058.ap-northeast-2.elb.amazonaws.com   80:30247/TCP,443:32732/TCP            2m3s
service/knative-internal-proxy   ClusterIP      10.100.212.181   <none>                                                                         80/TCP,443/TCP                        2m3s

NAME                                     READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/discovery                1/1     1            1           2m3s
deployment.apps/gloo                     1/1     1            1           2m3s
deployment.apps/ingress                  1/1     1            1           2m3s
deployment.apps/knative-external-proxy   1/1     1            1           2m3s
deployment.apps/knative-internal-proxy   1/1     1            1           2m3s

NAME                                                DESIRED   CURRENT   READY   AGE
replicaset.apps/discovery-5dc96cbb4d                1         1         1       2m3s
replicaset.apps/gloo-6d86dc87c8                     1         1         1       2m3s
replicaset.apps/ingress-6f95fd7dc                   1         1         1       2m3s
replicaset.apps/knative-external-proxy-f4f67644d    1         1         1       2m3s
replicaset.apps/knative-internal-proxy-7cd8448b58   1         1         1       2m3s
[root@ip-192-168-114-198 ~]# 

> kubectl get all -n knative-serving

[root@ip-192-168-114-198 ~]# kubectl get all -n knative-serving
NAME                                  READY   STATUS    RESTARTS   AGE
pod/activator-77fc555665-q4sf9        1/1     Running   0          3m21s
pod/autoscaler-5c98b7c9b6-dvbt9       1/1     Running   0          3m21s
pod/autoscaler-hpa-5cfd4f6845-l2jvx   1/1     Running   0          3m21s
pod/controller-7fd74c8f67-nthjj       1/1     Running   0          3m21s
pod/webhook-74847bb77c-v4h2l          1/1     Running   0          3m21s

NAME                        TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                     AGE
service/activator-service   ClusterIP   10.100.212.5     <none>        80/TCP,81/TCP,9090/TCP      3m21s
service/autoscaler          ClusterIP   10.100.106.32    <none>        8080/TCP,9090/TCP,443/TCP   3m21s
service/controller          ClusterIP   10.100.203.250   <none>        9090/TCP                    3m21s
service/webhook             ClusterIP   10.100.103.172   <none>        443/TCP                     3m21s

NAME                             READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/activator        1/1     1            1           3m21s
deployment.apps/autoscaler       1/1     1            1           3m21s
deployment.apps/autoscaler-hpa   1/1     1            1           3m21s
deployment.apps/controller       1/1     1            1           3m21s
deployment.apps/webhook          1/1     1            1           3m21s

NAME                                        DESIRED   CURRENT   READY   AGE
replicaset.apps/activator-77fc555665        1         1         1       3m21s
replicaset.apps/autoscaler-5c98b7c9b6       1         1         1       3m21s
replicaset.apps/autoscaler-hpa-5cfd4f6845   1         1         1       3m21s
replicaset.apps/controller-7fd74c8f67       1         1         1       3m21s
replicaset.apps/webhook-74847bb77c          1         1         1       3m21s

NAME                                            REFERENCE              TARGETS          MINPODS   MAXPODS   REPLICAS   AGE
horizontalpodautoscaler.autoscaling/activator   Deployment/activator   <unknown>/100%   1         20        1          3m21s
[root@ip-192-168-114-198 ~]# 

gloo로 knative를 설치하면 gloo 컴포넌트와 함께 serving 컴포넌트가 설치된다.

4. Knative Serving 설치

추가로 knative build 컴포넌트를 설치한다. 이를 이용하여 배포 이미지를 빌드할 수 있다.

> kubectl apply -f https://github.com/knative/build/releases/download/v0.7.0/build.yaml

[root@ip-192-168-114-198 knative]# kubectl apply -f https://github.com/knative/build/releases/download/v0.7.0/build.yaml
namespace/knative-build unchanged
podsecuritypolicy.policy/knative-build configured
clusterrole.rbac.authorization.k8s.io/knative-build-admin configured
serviceaccount/build-controller unchanged
clusterrolebinding.rbac.authorization.k8s.io/build-controller-admin unchanged
customresourcedefinition.apiextensions.k8s.io/builds.build.knative.dev unchanged
customresourcedefinition.apiextensions.k8s.io/buildtemplates.build.knative.dev unchanged
customresourcedefinition.apiextensions.k8s.io/clusterbuildtemplates.build.knative.dev unchanged
customresourcedefinition.apiextensions.k8s.io/images.caching.internal.knative.dev configured
service/build-controller unchanged
service/build-webhook configured
image.caching.internal.knative.dev/creds-init configured
image.caching.internal.knative.dev/git-init configured
image.caching.internal.knative.dev/gcs-fetcher unchanged
image.caching.internal.knative.dev/nop configured
configmap/config-logging unchanged
configmap/config-observability created
deployment.apps/build-controller configured
deployment.apps/build-webhook configured
[root@ip-192-168-114-198 knative]#

Knative build 모듈을 배포하다 아래와 같은 에러가 나올 경우에는 현재 지원하는 버전을 확인하여 최신 Release 버전을 설치하도록 한다.

[Error Message]

{
  "level":"error",
  "logger":"webhook",
  "caller":"webhook/webhook.go:315",
  "msg":"failed to register webhook",
  "knative.dev/controller":"webhook",
  "error":"failed to fetch our deployment: the server could not find the requested resource",
  "stacktrace":"github.com/knative/build/vendor/github.com/knative/pkg/webhook.(*AdmissionController).Run/go/src/github.com/knative/build/vendor/github.com/knative/pkg/webhook/webhook.go:315main.main /go/src/github.com/knative/build/cmd/webhook/main.go:92runtime.main /usr/local/go/src/runtime/proc.go:200"
}

[Release 확인]

Knative Build Release - https://github.com/knative/build/releases

 

Releases · knative/build

A Kubernetes-native Build resource. Contribute to knative/build development by creating an account on GitHub.

github.com

설치가 완료되면 아래와 같이 gloo-system, knative-build, knative-serving namespace에 Pod 들이 기동되어 있는 것을 확인할 수 있다.

[root@ip-192-168-114-198 knative]# kubectl get pods --all-namespaces
NAMESPACE         NAME                                      READY   STATUS    RESTARTS   AGE
gloo-system       discovery-5dc96cbb4d-94fbn                1/1     Running   0          10h
gloo-system       gloo-6d86dc87c8-hb58b                     1/1     Running   0          10h
gloo-system       ingress-6f95fd7dc-bj65l                   1/1     Running   0          10h
gloo-system       knative-external-proxy-f4f67644d-drzps    1/1     Running   0          10h
gloo-system       knative-internal-proxy-7cd8448b58-qcfgs   1/1     Running   0          10h
knative-build     build-controller-766fdf748f-wrqjx         1/1     Running   0          35s
knative-build     build-webhook-68d987cd9f-fpwmj            1/1     Running   0          35s
knative-serving   activator-77fc555665-q4sf9                1/1     Running   0          10h
knative-serving   autoscaler-5c98b7c9b6-dvbt9               1/1     Running   0          10h
knative-serving   autoscaler-hpa-5cfd4f6845-l2jvx           1/1     Running   0          10h
knative-serving   controller-7fd74c8f67-nthjj               1/1     Running   0          10h
knative-serving   webhook-74847bb77c-v4h2l                  1/1     Running   0          10h
kube-system       aws-node-gkrkk                            1/1     Running   0          12h
kube-system       aws-node-wbq5b                            1/1     Running   0          12h
kube-system       coredns-7dd7f84d9-9f97n                   1/1     Running   0          12h
kube-system       coredns-7dd7f84d9-brzqd                   1/1     Running   0          12h
kube-system       kube-proxy-j2np9                          1/1     Running   0          12h
kube-system       kube-proxy-vglbj                          1/1     Running   0          12h
[root@ip-192-168-114-198 knative]#

위와 같이 Pod가 정상 기동되었는지 여부를 확인하고 정상적이면 Serverless Cloud Native Application을 빌드 및 배포해 보도록 하자.


Knative Build

앞서 살펴본 바와 같이 Gloo는 Knative의 핵심 기능 중 Build와 Serving을 지원하지만, Event는 지원하지 않는다. 따라서 가이드에서는 Build와 Serving만 살펴보도록 하자.

먼저 Knaive Build를 수행하는 과정이다. 이 과정에서는 다음과 같은 Step이 진행된다.

1) Git Clone

2) Docker Build

3) Docker Tagging

4) Docker Login

5) Docker Push

위와 같은 과정이 수행되는 것은 실제 클라우드 환경에 배포를 진행하는 CI 단계와 동일하다는 것을 알 수 있다. 이는 CLI 상에서 진행되기 때문에 최근에는 Knative Build가 Deprecated 되고 Tekton이라는 CI Tool이 그 대처 솔루션으로 권고되고 있다.

다만 이번 가이드에서는 Knative Build를 사용하여 빌드를 진행해 보도록 하자. (이후에 기회가 된다면 Tekton에 대해서도 다뤄볼 예정이다.)

1. Docker Registry Credential 등록

Docker Image를 Push하기 위한 Secret과 ServiceAccount를 다음과 같이 각각 생성한다.

> secret.yaml

apiVersion: v1
kind: Secret
metadata:
  name: dockerhub-credential
  annotations:
    build.knative.dev/docker-0: https://index.docker.io/v1/
type: kubernetes.io/basic-auth
data:
  username: USERNAME_ENCODE_BASE64
  password: PASSWORD_ENCODE_BASE64

Docker image를 저장할 Registry(DockerHub, Nexus, ECR 등)의 ID/PW를 BASE64로 인코딩한 정보를 data에 등록한다. (본 예시는 dockerhub에 저장한다.)

> sa.yaml

apiVersion: v1
kind: ServiceAccount
metadata:
  name: build-serverless
secrets:
  - name: dockerhub-credential

위와 같이 작성 후 각각 반영한다.

[root@ip-192-168-114-198 knative]# kubectl apply -f secret.yaml 
secret/dockerhub-credential created
[root@ip-192-168-114-198 knative]# kubectl apply -f sa.yaml 
serviceaccount/build-serverless created
[root@ip-192-168-114-198 knative]#

2. Test Code & Dockerfile 작성

> app.py

import os

from flask import Flask

app = Flask(__name__)


@app.route('/')
def hello_world():
    target = os.environ.get('TARGET', 'NOT SPECIFIED')
    return 'Hi!! Serverless: {}!\n'.format(target)


if __name__ == "__main__":
    app.run(debug=True, host='0.0.0.0', port=int(os.environ.get('PORT', 8080)))

target 변수를 받아 출력하는 간단한 Python 코드이다.

> Dockerfile

FROM python:alpine

ENV APP_HOME /app
COPY . $APP_HOME
WORKDIR $APP_HOME

RUN pip install Flask

ENTRYPOINT ["python"]
CMD ["app.py"]

Python을 빌드하는 Dockerfile을 작성한다.

위와 같이 작성한 파일을 github 등에 저장한 후 Knative Build에서 참조하도록 한다.

> https://github.com/sonnaraon/knative-sample 

 

sonnaraon/knative-sample

knative sample project. Contribute to sonnaraon/knative-sample development by creating an account on GitHub.

github.com

3. build.yaml 작성

build object를 생성하기 위한 build.yaml 파일을 작성한다.

> build-python.yaml

apiVersion: build.knative.dev/v1alpha1
kind: Build
metadata:
  name: python-build
spec:
  serviceAccountName: build-serverless
  source:
    git:
      url: https://github.com/sonnaraon/knative-sample.git
      revision: master
  steps:
  - name: build-and-push
    image: gcr.io/kaniko-project/executor:v0.1.0
    args:
    - --dockerfile=/workspace/Dockerfile
    - --destination=docker.io/nara0617/hello-python:latest

- spec.source.git : Git Clone

- spec.steps : Docker build & push

4. Knative Build 수행

작성한 build-python.yaml 파일을 적용하면 아래와 같이 build object가 생성되며, 일정 시간 후 build 상태가 True로 변경되는 것을 확인할 수 있다.

[root@ip-192-168-114-198 knative]# kubectl apply -f build-python.yaml 
build.build.knative.dev/python-build created
[root@ip-192-168-114-198 knative]# kubectl get build -w
NAME           SUCCEEDED   REASON    STARTTIME   COMPLETIONTIME
python-build   Unknown     Pending   5s          
python-build   Unknown     Pending   5s          
python-build   Unknown     Pending   6s          
python-build   Unknown     Pending   27s         
python-build   True                  28s

만약 이 Step이 False가 나올 경우에는 아래 Pod의 Log와 Describe 등을 점검한다.

[root@ip-192-168-114-198 knative]# kubectl get pods
NAME                      READY   STATUS      RESTARTS   AGE
python-build-pod-2744b6   0/1     Completed   0          3m56s
[root@ip-192-168-114-198 knative]#

위와 같이 정상적으로 완료되었을 경우 Completed 상태가 나온다. 정상적으로 Build Step이 완료되면, 아래와 같이 spec.steps.args --destination에 정의한 Repository에 이미지가 저장된다.

사실 이 과정은 앞서 Jenkins에서 CI 과정을 통해 수행한 내용과 거의 같다고 볼 수 있다. Git Clone & Docker Image를 생성하는 과정까지가 CNA에서 CI 과정이라고 볼 수 있으며, Knative Build는 동일한 과정을 담당한다고 볼 수 있다. 사실 이 과정은 Knative Build를 사용하지 않고 다른 CI 도구를 사용해도 상관이 없으며, Knative 진영에서는 Tekton을 권고하고 있다.

이제 여기까지 구성이 완료되면, 다음으로 Knative Serving 단계를 진행한다.


Knative Serving

1. Knative Service 생성 및 배포

먼저 Build 단계에서 생성한 Docker Image를 기반으로 Knative Service를 생성한다.

> ksvc.yaml

apiVersion: serving.knative.dev/v1alpha1
kind: Service
metadata:
  name: helloworld-python
  namespace: default
spec:
  runLatest:
    configuration:
      revisionTemplate:
        spec:
          container:
            image: nara0617/hello-python:latest
            env:
            - name: TARGET
              value: "Python Sample v1"

생성 후 배포를 진행한다.

[root@ip-192-168-114-198 knative]# kubectl apply -f ksvc.yaml
service.serving.knative.dev/helloworld-python created
[root@ip-192-168-114-198 knative]#

2. 배포 상태 확인

[root@ip-192-168-114-198 knative]# kubectl get all
NAME                          READY   STATUS      RESTARTS   AGE
pod/python-build-pod-2744b6   0/1     Completed   0          26m

NAME                                      TYPE           CLUSTER-IP       EXTERNAL-IP                                            PORT(S)             AGE
service/helloworld-python                 ExternalName   <none>           knative-internal-proxy.gloo-system.svc.cluster.local   <none>              96s
service/helloworld-python-f8j5n           ClusterIP      10.100.11.213    <none>                                                 80/TCP              105s
service/helloworld-python-f8j5n-metrics   ClusterIP      10.100.235.122   <none>                                                 9090/TCP,9091/TCP   105s
service/helloworld-python-f8j5n-private   ClusterIP      10.100.241.241   <none>                                                 80/TCP,8022/TCP     105s
service/kubernetes                        ClusterIP      10.100.0.1       <none>                                                 443/TCP             33h

NAME                                                 READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/helloworld-python-f8j5n-deployment   0/0     0            0           105s

NAME                                                            DESIRED   CURRENT   READY   AGE
replicaset.apps/helloworld-python-f8j5n-deployment-5754869ffc   0         0         0       105s

NAME                                          URL                                            READY   REASON
route.serving.knative.dev/helloworld-python   http://helloworld-python.default.example.com   True    

NAME                                            URL                                            LATESTCREATED             LATESTREADY               READY   REASON
service.serving.knative.dev/helloworld-python   http://helloworld-python.default.example.com   helloworld-python-f8j5n   helloworld-python-f8j5n   True    

NAME                                                   CONFIG NAME         K8S SERVICE NAME          GENERATION   READY   REASON
revision.serving.knative.dev/helloworld-python-f8j5n   helloworld-python   helloworld-python-f8j5n   1            True    

NAME                                                  LATESTCREATED             LATESTREADY               READY   REASON
configuration.serving.knative.dev/helloworld-python   helloworld-python-f8j5n   helloworld-python-f8j5n   True    

NAME                                   SUCCEEDED   REASON   STARTTIME   COMPLETIONTIME
build.build.knative.dev/python-build   True                 26m         

NAME                                                               AGE
image.caching.internal.knative.dev/helloworld-python-f8j5n-cache   106s
[root@ip-192-168-114-198 knative]#

위와 같이 Knative Service를 배포하면, ksvc, configuration, route, revision Object가 생성된다.

3. knctl 활용

위와 같이 yaml 파일로 ksvc 생성 시 자동으로 route, configuration, revision 등이 생성된다. 이를 knctl 명령어를 활용하여 보다 세부적으로 각 Object를 생성하고 확인할 수 있다.

a. knctl 설치

[root@ip-192-168-114-198 ~]# wget https://github.com/cppforlife/knctl/releases/download/v0.3.0/knctl-linux-amd64
--2020-12-26 23:17:21--  https://github.com/cppforlife/knctl/releases/download/v0.3.0/knctl-linux-amd64
Resolving github.com (github.com)... 15.164.81.167
Connecting to github.com (github.com)|15.164.81.167|:443... connected.
HTTP request sent, awaiting response... 302 Found
Location: https://github-production-release-asset-2e65be.s3.amazonaws.com/143948317/78456200-508b-11e9-81d1-539559b46c3a?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20201226%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20201226T231721Z&X-Amz-Expires=300&X-Amz-Signature=85f7515634d659f92d0ca367a684def0cc32aeefc6b1f9ba0faa978147308cc0&X-Amz-SignedHeaders=host&actor_id=0&key_id=0&repo_id=143948317&response-content-disposition=attachment%3B%20filename%3Dknctl-linux-amd64&response-content-type=application%2Foctet-stream [following]
--2020-12-26 23:17:21--  https://github-production-release-asset-2e65be.s3.amazonaws.com/143948317/78456200-508b-11e9-81d1-539559b46c3a?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20201226%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20201226T231721Z&X-Amz-Expires=300&X-Amz-Signature=85f7515634d659f92d0ca367a684def0cc32aeefc6b1f9ba0faa978147308cc0&X-Amz-SignedHeaders=host&actor_id=0&key_id=0&repo_id=143948317&response-content-disposition=attachment%3B%20filename%3Dknctl-linux-amd64&response-content-type=application%2Foctet-stream
Resolving github-production-release-asset-2e65be.s3.amazonaws.com (github-production-release-asset-2e65be.s3.amazonaws.com)... 52.217.48.156
Connecting to github-production-release-asset-2e65be.s3.amazonaws.com (github-production-release-asset-2e65be.s3.amazonaws.com)|52.217.48.156|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 36744648 (35M) [application/octet-stream]
Saving to: [22;13Hknctl-linux-amd64[24;1H100%[=====================================================================================================================================================================>] 36,744,648  6.26MB/s   in 6.8s

2020-12-26 23:17:29 (5.13 MB/s) - [26;36Hknctl-linux-amd64[26;55Hsaved [36744648/36744648]

[root@ip-192-168-114-198 ~]# mv knctl-* /usr/local/bin/knctl
[root@ip-192-168-114-198 ~]# chmod +x /usr/local/bin/knctl
[root@ip-192-168-114-198 ~]# knctl version
Client Version: 0.3.0

Succeeded
[root@ip-192-168-114-198 ~]# 

b. knctl 활용

아래와 같이 knctl을 활용하여 knative 관련 Object 정보를 확인할 수 있다.

[root@ip-192-168-114-198 knative]# knctl service list
Services in namespace 'default'

Name               Domain  Annotations  Conditions  Age  
helloworld-python  -       -            3 OK / 3    45m  

1 services

Succeeded
[root@ip-192-168-114-198 knative]# knctl route list
Routes in namespace 'default'

Name               Domain  Traffic                    Annotations  Conditions  Age  
helloworld-python  -       100% -> helloworld-python  -            3 OK / 3    46m  

1 routes

Succeeded
[root@ip-192-168-114-198 knative]# knctl revision list
Revisions

Service            Name                     Tags  Annotations  Conditions  Age  Traffic  
helloworld-python  helloworld-python-f8j5n  -     -            4 OK / 4    46m  100% ->   

1 revisions

Succeeded
[root@ip-192-168-114-198 knative]#

4. 테스트

호출은 다음과 같은 도메인으로 접근할 수 있다.

[root@ip-192-168-114-198 knative]# kubectl get service -n gloo-system
NAME                     TYPE           CLUSTER-IP       EXTERNAL-IP                                                                    PORT(S)                               AGE
gloo                     ClusterIP      10.100.230.54    <none>                                                                         9977/TCP,9976/TCP,9988/TCP,9979/TCP   31h
knative-external-proxy   LoadBalancer   10.100.68.120    afe2c222e1558413d8e8acfd0ef74357-1341022058.ap-northeast-2.elb.amazonaws.com   80:30247/TCP,443:32732/TCP            31h
knative-internal-proxy   ClusterIP      10.100.212.181   <none>                                                                         80/TCP,443/TCP                        31h
[root@ip-192-168-114-198 knative]# kubectl get ksvc
NAME                URL                                            LATESTCREATED             LATESTREADY               READY   REASON
helloworld-python   http://helloworld-python.default.example.com   helloworld-python-f8j5n   helloworld-python-f8j5n   True    
[root@ip-192-168-114-198 knative]# 

gloo의 External IP를 ksvc host로 호출하면 아래와 같이 호출할 수 있다.

> curl -H "Host: helloworld-python.default.example.com" http://afe2c222e1558413d8e8acfd0ef74357-1341022058.ap-northeast-2.elb.amazonaws.com 

gloo는 Public Cloud 상에 배치 될 경우 LoadBalancerType으로 자동으로 External Proxy를 생성한다. 

a. pod 확인

테스트 전 default namespace에 pod를 확인해 보자.

[root@ip-192-168-114-198 knative]# kubectl get pods -w
NAME                      READY   STATUS      RESTARTS   AGE
python-build-pod-2744b6   0/1     Completed   0          36m

위와 같이 현재 Knative Build Pod 이외에 기동되어 있는 Pod는 없는 상태이다.

b. curl 호출

[root@ip-192-168-114-198 knative]# curl -H "Host: helloworld-python.default.example.com" http://afe2c222e1558413d8e8acfd0ef74357-1341022058.ap-northeast-2.elb.amazonaws.com
Hi!! Serverless: Python Sample v1!
[root@ip-192-168-114-198 knative]# 

위와 같이 호출 시 Cold Start로 인해 약간의 Delay(약 3~5초) 발생 후 호출이 된다.

마찬가지로 hosts 파일 또는 Route 53 등을 이용하여 브라우저를 통해 호출할 수도 있다.

# 참조 (Cold Start)

새로운 요청 또는 더 많은 동시 처리를 위해 새로운 함수를 생성해야 하는 경우 배포 패키지의 크기와 코드 실행 시간 및 코드의 초기화 시간에 따라 새 실행 환경으로 호출을 라우팅할 때 지연 시간이 발생할 수 있다. 이 지연 시간을 일반적으로 "콜드 스타트(Cold start)"라고 한다.

> http://aws.amazon.com/ko/blogs/korea/new-provisioned-concurrency-for-lambda-functions/

 

AWS Lambda 함수, Provisioned Concurrency를 통해 빠른 성능 제공 (서울 리전 포함) | Amazon Web Services

AWS Lambda가 출시되고 5년이 흘렀지만 여전히 팀은 더 쉽게 애플리케이션을 구축하고 실행할 수 있는 새로운 방법을 찾고 있습니다. 특히, 중요 애플리케이션이 서버리스로 이동하면서 애플리케

aws.amazon.com

c. Serverless Pod 기동 종료 확인

[root@ip-192-168-114-198 knative]# kubectl get pods -w
NAME                      READY   STATUS      RESTARTS   AGE
python-build-pod-2744b6   0/1     Completed   0          36m
helloworld-python-f8j5n-deployment-5754869ffc-txvdh   0/2     Pending     0          0s
helloworld-python-f8j5n-deployment-5754869ffc-txvdh   0/2     Pending     0          0s
helloworld-python-f8j5n-deployment-5754869ffc-txvdh   0/2     ContainerCreating   0          0s
helloworld-python-f8j5n-deployment-5754869ffc-txvdh   1/2     Running             0          3s
helloworld-python-f8j5n-deployment-5754869ffc-txvdh   2/2     Running             0          4s
helloworld-python-f8j5n-deployment-5754869ffc-txvdh   2/2     Terminating         0          64s
helloworld-python-f8j5n-deployment-5754869ffc-txvdh   1/2     Terminating         0          85s
helloworld-python-f8j5n-deployment-5754869ffc-txvdh   0/2     Terminating         0          85s
helloworld-python-f8j5n-deployment-5754869ffc-txvdh   0/2     Terminating         0          93s
helloworld-python-f8j5n-deployment-5754869ffc-txvdh   0/2     Terminating         0          93s

위와 같이 호출 시작 후 약 4초 뒤 Pod가 생성 및 기동이 완료되고, 비즈니스 처리가 완료된 후 60초 후(Container 생성 후 64초 후) Pod가 자동으로 Terminating 되는 것을 알 수 있다.

d. 반복 호출

다음으로 아래와 같이 동일한 호출을 다섯번 반복적으로 호출해 보자.

[root@ip-192-168-114-198 knative]# curl -H "Host: helloworld-python.default.example.com" http://afe2c222e1558413d8e8acfd0ef74357-1341022058.ap-northeast-2.elb.amazonaws.com
Hi!! Serverless: Python Sample v1!
[root@ip-192-168-114-198 knative]# curl -H "Host: helloworld-python.default.example.com" http://afe2c222e1558413d8e8acfd0ef74357-1341022058.ap-northeast-2.elb.amazonaws.com
Hi!! Serverless: Python Sample v1!
[root@ip-192-168-114-198 knative]# curl -H "Host: helloworld-python.default.example.com" http://afe2c222e1558413d8e8acfd0ef74357-1341022058.ap-northeast-2.elb.amazonaws.com
Hi!! Serverless: Python Sample v1!
[root@ip-192-168-114-198 knative]# curl -H "Host: helloworld-python.default.example.com" http://afe2c222e1558413d8e8acfd0ef74357-1341022058.ap-northeast-2.elb.amazonaws.com
Hi!! Serverless: Python Sample v1!
[root@ip-192-168-114-198 knative]# curl -H "Host: helloworld-python.default.example.com" http://afe2c222e1558413d8e8acfd0ef74357-1341022058.ap-northeast-2.elb.amazonaws.com
Hi!! Serverless: Python Sample v1!
[root@ip-192-168-114-198 knative]#

위와 같이 반복적으로 호출할 경우의 Pod를 확인해 보면 다음과 같다.

[root@ip-192-168-114-198 knative]# kubectl get pods -w
NAME                      READY   STATUS      RESTARTS   AGE
python-build-pod-2744b6   0/1     Completed   0          44m
helloworld-python-f8j5n-deployment-5754869ffc-rwqvh   0/2     Pending     0          0s
helloworld-python-f8j5n-deployment-5754869ffc-rwqvh   0/2     Pending     0          0s
helloworld-python-f8j5n-deployment-5754869ffc-rwqvh   0/2     ContainerCreating   0          0s
helloworld-python-f8j5n-deployment-5754869ffc-rwqvh   1/2     Running             0          2s
helloworld-python-f8j5n-deployment-5754869ffc-rwqvh   2/2     Running             0          2s
helloworld-python-f8j5n-deployment-5754869ffc-rwqvh   2/2     Terminating         0          86s
helloworld-python-f8j5n-deployment-5754869ffc-rwqvh   1/2     Terminating         0          106s
helloworld-python-f8j5n-deployment-5754869ffc-rwqvh   0/2     Terminating         0          107s
helloworld-python-f8j5n-deployment-5754869ffc-rwqvh   0/2     Terminating         0          111s
helloworld-python-f8j5n-deployment-5754869ffc-rwqvh   0/2     Terminating         0          111s

위와 같이 현재 기동되어 있는 Serverless Pod가 종료되기 전 상태일 경우 Pod를 추가로 기동하지 않고 재 활용된다.


결론

AWS Lambda는 이미 유명한 Serverless Computing으로 다양한 비즈니스에서 활용되고 있다. 이와 같은 Public Cloud 상의 Serverless Computing 기술은 다양하게 활용되고 있지만, 종족성을 갖고 있어 Multi/Hybrid Cloud 환경에 적용하기에는 제약이 있다.

Knative 프로젝트를 활용하면 특정 Public Cloud에 종속적인 서비스와 다르게 Public Cloud는 물론 On-Prem Kubernetes 기반에서 이와 같은 Serverless Cloud Native Application을 개발하도록 지원할 수 있으며, Lock-In 요소를 최소화 할 수 있다.

현재 Knative는 Serverless Computing을 이끌어가는 대표적인 오픈소스 소프트웨어로써 자리잡고 있으며, 앞으로 지속적인 성장을 예고하고 있다. 가이드에서 다룬 내용은 Knative Build / Serving 정도이지만, Monitoring, Eventing 등 다양한 방법으로 Knative를 적용해 볼 수 있으며, 이에 대한 활용 방법들은 차차 알아보도록 하자.

728x90
반응형