공부하고 기록하는, 경제학과 출신 개발자의 노트

학습일지/Knative

Knative Series 2 - Knative 101

inspirit941 2021. 12. 20. 10:50
반응형

강연자 : Carlos.

  • ibm cloud의 cloud native Architect로 재직중
    • Modernizing Customers' Application into K8s (Openshift)
    • Serverless 쪽 오픈소스 프로젝트 Contributor (OpenWhisk, Knative)

Knative에서 제공하는 두 개의 component -> Serving, Eventing. 각각 독립된 컴포넌트로 사용이 가능하다.

  1. Serving -> Scaling to Zero, traffic splitting
    • 일반적으로 kubernetes를 사용해서 scaling 기능을 적용하려면
      • ingress : yaml 세팅법, https를 위한 TLS 적용을 secret으로 등록하기, Endpoint를 service에 연결하기
      • Deployment : selectors (labels) 세팅법. service 찾고 Port 연결하기, configuring a container의 반복...
    • 위와 같은 작업을 자동화하고, 자동으로 scale to zero를 지원함.
    • 새 버전이 출시됐을 때 점진적으로 트래픽을 올리거나, metrics를 확인하며 트래픽을 변경하는 등의 로직을 수행하려면 istio / Contour를 별도로 세팅하고 설정을 적용하는 등 복잡함.
  2. Eventing -> handing the event Asynchronous way. 어떤 일이 발생하면, 특정 동작을 수행하도록 하는 작업을 Cloud Event라는 CNCF 표준에 맞게 적용 가능.
    • ex) Webhook (github)
    • 일종의 Building Block to manage cloud events - getting source / manage the Sink.

https://knative.dev/docs/install/serving/install-serving-with-yaml/

강의에서는 kubernetes cluster를 노트북에 세팅하기 위해 kind를 사용.

  • k8s 여러 버전을 테스트할 수 있어 편리하다고 함.

knative를 실행할 때 networking layer가 하나 필요함. istio일 수도 있고 Contour일 수도 있음.

  • 강의에서는 Envoy 기반의 간단한 레이어인 contour를 사용할 예정.
    • contour도 knative 프로젝트에서 관리되고 있는 프로덕트 중 하나.
    • knative에서 요구하는 작업을 해줄 수 있는 small envoy configuration controller.
  • networking layer : Ingress -> data plane에서 traffic split 등의 역할을 담당하는 영역.

스크린샷 2021-12-19 오후 12 33 18

kn cli 설치까지 마무리한 상태.

 

 


기본적으로 Container 형태를 지원함. container가 있으면 kn service create 명령어로 설치할 수 있음.

이 강의에서는 container의 build 관련해서는 길게 이야기하지 않을 예정. knative의 한 과정이고 stacked into pipelines. 어떤 빌드팩으로 빌드하건 일단 container를 생성했다는 전제로 시작함

https://knative.dev/docs/getting-started/first-service/

kn service create hello \
--image gcr.io/knative-samples/helloworld-go \
--port 8080 \
--env TARGET=World \
--revision-name=world
  • 포트는 애플리케이션에서 사용하는 포트를 쓰면 된다. nodejs는 보통 3000을 쓸 거고.. 컨테이너에서 외부연결에 사용하는 포트를 쓰면 됨.

스크린샷 2021-12-19 오후 12 44 15

 


 

Scale to Zero

스크린샷 2021-12-19 오후 12 52 28

  • service create로 생성했을 때에는 kubectl get pods 로 pod 상태를 확인했을 때 running이지만, 생성된 http url에 접근하지 않을 경우 pod이 자동으로 제거된다.
  • http url로 다시 서비스에 접근할 경우, Pending -> ContainerCreating -> Running 상태로 변경된다. 이 상태로 변경되기까지는 약 3초가 걸렸다.

knative Service를 '사용자가 언제든 접근할 수 있는 웹사이트'라고 생각한다면 scale to 1이 나을 수 있지만, service 간 호출이거나 필요한 경우에만 간혹 호출되는 형태의 microService 조합이라면 scale to Zero를 적용할 수 있다.

 


 

kn service update hello \
--env TARGET=Knative \
--revision-name=knative

knative Service의 configuration을 변경할 때마다 새로운 Revision이 생성된다. kn cli로 revision에 특정 이름을 지정할 수도 있고, yaml 파일에 설정할 수도 있다. 기본적으로는 unique id가 되도록 만들어진다.

 

스크린샷 2021-12-19 오후 1 04 08

  • 새 revision이 생성되면, 해당 revision으로 트래픽이 100% 이전된다.
kn service update hello \
--traffic hello-world=50 \
--traffic @latest=50
  • 만들어진 revision별로 트래픽 양을 조절할 수 있다. 이 작업은 networking layer인 contour, kourier, Istio 등에서 수행한다.

스크린샷 2021-12-19 오후 1 04 55


중간질문

Q. 배포하는 모든 pod마다 envoy Sidecar가 기본으로 설정되어 있나?

  • A.kube-proxy라는 게 있다. pod가 생성될 때 내부에 두 개의 컨테이너가 생성됨.
    • user container
    • kube-proxy : 약갼의 knative code로 proxy처럼 작동함.
      • concurrency Check와 Metrics 담당.
    • 만약 여기에 istio sidecar를 추가하면, 컨테이너가 하나 더 생긴다. 그 컨테이너가 envoy.

기본적으로 트래픽은 kube-proxy를 통해 먼저 들어오고, kube-proxy가 요청을 user container로 보내는 것.

 

다운로드 (6)

 

  • Concurrency: 하나의 container 당 request Concurrency를 1로 설정하고 사용하는 경우가 있다. OpenWrisk나 AWS Lambda같은 FaaS가 여기 해당함.
    • 즉 1 instance of Container -> can handle 1 Request at a Time.
    • Runtime에서 Threading을 허용하지 않는다던가, Connection이 여러 개 이루어졌을 때 발생할 수 있는 에러 핸들링이 어렵다거나... 등등의 이유.
    • High Performance인 application을 생각한다면 concurrency가 1에서 머무르면 안 된다.
  • Metrics: Concurrency 세팅값과 실제 concurrent하게 실행되는 값을 비교해서, 기준치를 초과할 경우 새 Pod을 생성하도록 한다.
    • Metrics의 값은 AutoScaler로 전달되고, autoScaler는 Deployment를 관리한다.

일반적으로 테스트에 가장 많이 쓰는 이미지는 nginx이니까 nginx로 테스트.

kn service create nginx --image nginx --port 80

강의 예시에서는 실제 real domain으로 url이 생성되도록 설정해뒀다. (domain mapping)

스크린샷 2021-12-19 오후 1 48 20

  • bitnami 이미지의 경우 8080 포트를 보도록 되어 있지만, image로 그냥 nginx 선택할 경우 포트는 80으로 해줘야 한다.

 

스크린샷 2021-12-19 오후 1 50 30

  • 처음 명령어로 만들어진 url은 http://형태로 되어 있지만, 다시 kn service list로 서비스를 확인해보면 https가 붙어 있는 걸 볼 수 있다.
    • auto TLS 설정을 하고, encrypt로 확인한 다음 Url이 정상인지 체크하기까지 약간의 딜레이가 있기 때문.
    • 아무 문제 없을 경우 ingress에 certificate를 설정해준다.

Knative Eventing

Cloud Event handling.

https://knative.dev/development/getting-started/first-broker/

eventing

  • 어느 k8s Service라도 event handling은 가능하다. 그래서 'addressable' 이라고도 부름. 도식에서는 Sink 영역이다.
    • external url / hostName, Service Inside a Cluster, Knative Service 등등.
  • Source : 이벤트를 보내는 쪽. Emit events.
    • CI/CD이거나, S3 storage에 파일을 업로드하는 등의 행위라거나, 구글 스프레드시트에서 파일을 수정하는 등...

이벤트를 발생시키면, Broker로 이벤트가 전송된다. Broker는 일종의 hub. 이 중 내가 필요로 하는 이벤트를 받아오기 위한 Trigger를 정의할 수 있다.

  • Broker는 보유한 dispatcher component로 조건에 맞는 trigger를 발동시킨다.
    • 이벤트를 트리거로 받아서 실행하는 것 -> FaaS에서도 사용하는 방식. FaaS 자체가 Event handling처럼 쓰일 수 있고, function의 파라미터로 event가 들어갈 수 있듯.
  • 트리거는 filter를 붙여서 사용한다.

k8s 1.17 기준 knative eventing 설치방법

https://knative.dev/docs/install/eventing/install-eventing-with-yaml/

  1. knative eventing 세팅

스크린샷 2021-12-19 오후 2 36 40

생성된 broker도 programmable URL 형태로 주어진다.

  1. Cloud Player installer 설치.

일종의 utility로, 웹 GUI로 클라우드 이벤트를 보내고 받는 등의 작업이 가능함. 즉 Source / Sink 역할을 둘 다 할 수 있음. Knative Service이므로 Scale to Zero가 가능함.

kn service create cloudevents-player \
--image ruromero/cloudevents-player:latest \
--env BROKER_URL=http://broker-ingress.knative-eventing.svc.cluster.local/default/example-broker

https://knative.dev/docs/getting-started/first-source/ 에서 자세한 실습내용을 확인할 수 있다.

 


 

  1. Create Event에서 새로운 이벤트를 생성한다.
    • 단, 이벤트를 생성하기만 하면 해당 이벤트를 받는 service가 없기 때문에 아무 일도 일어나지 않는다.
    • 따라서 해당 이벤트를 broker에 전달하고,
      스크린샷 2021-12-19 오후 10 55 05
  2. 이벤트를 받을 수 있는 Trigger를 생성한다.
    • https://knative.dev/docs/getting-started/first-trigger/
    • kn trigger create cloudevents-trigger --sink cloudevents-player --broker example-broker
    • 해당 이벤트를 처리할 Sink는 cloudevents-player로 설정했다. GUI에서 이벤트 확인이 가능하도록.
    • broker 이름에는 in-memory broker 이름을 넣어준다.
  3. 다시 이벤트를 보내보면 아까와의 차이를 느낄 수 있다.

스크린샷 2021-12-19 오후 11 00 28

  • 이벤트를 보냈다는 send와 함께, 트리거가 이벤트를 받았다는 Status 체크표시가 같이 표시된다.

cf. Broker의 url을 외부로 노출해서 http 요청을 받도록 세팅하기.

  • 기본적으로 knative service는 url을 갖고, 외부로 노출할 수 있다.
  • broker도 knative service다.

domain Mapping을 broker에 적용해서 사용할 수 있음. (knative 0.19에서는 api가 지원되지 않음.)

kubectl apply -f - <<EOF
apiVersion: networking.internal.knative.dev/v1alpha1
kind: ClusterDomainClaim
metadata:
  name: broker-ingress.knative-eventing.127.0.0.1.nip.io
spec:
  namespace: knative-eventing
EOF
kubectl -n knative-eventing apply -f - << EOF
apiVersion: serving.knative.dev/v1alpha1
kind: DomainMapping
metadata:
  name: broker-ingress.knative-eventing.127.0.0.1.nip.io
spec:
  ref:
    name: broker-ingress
    kind: Service
    apiVersion: v1
EOF
sleep 2
kubectl wait -n knative-eventing DomainMapping broker-ingress.knative-eventing.127.0.0.1.nip.io --timeout=1s --for=condition=Ready > /dev/null
  • creating a url / hostname available outside a cluster. it will hit the broker.
  • 위의 명령어에서 url에 해당하는 부분은 broker-ingress.knative-eventing.127.0.0.1.nip.io
curl -s "http://broker-ingress.knative-eventing.127.0.0.1.nip.io/default/example-broker" \
  -X POST
  -H "Ce-Id: say-hello" \
  -H "Ce-Specversion: 1.0" \
  -H "Ce-Type: greeting" \
  -H "Ce-Source: not-sendoff" \
  -H "Content-Type: application/json" \
  -d '{"msg":"hello knative!"}'

이제, 열려 있는 broker url로 이벤트를 보낼 service를 생성한다.

kn service create event-display --scale-min "1" --image "gcr.io/knative-releases/knative.dev/eventing-contrib/cmd/event_display"

해당 이벤트가 받을 trigger를 생성한다.

kn trigger create event-display-trigger --sink "event-display" --broker "example-broker" --filter "type=greeting"

스크린샷 2021-12-20 오전 10 25 36

  • sink: 해당 이벤트를 처리할 service
  • broker: 이벤트를 받아올 트리거 설정
  • filter: 어떤 이벤트만 받아올 것인지 설정

stern event-display -c user-container 로 event-display의 output을 확인할 수 있다.

이벤트를 curl로 보냈을 때 event-display에 찍히는 로그.

스크린샷 2021-12-20 오전 10 26 05


이후 몇 가지 knative 특이점 설명

  • k8s는 기본적으로 같은 namespace일 경우 호출할 때 namespace를 생략할 수 있지만, knative는 동일한 namespace에 생성되어 있더라도 namespace를 지정해서 호출해야 한다. (k8s에서 다른 namespace의 리소스 호출하는 것처럼)
  • knative로 오는 트래픽은 기본적으로 ingress를 통과해야 하는데, istio / contour등 ingress를 담당하는 컴포넌트들은 같은 namespace에 생성되어 있지 않기 때문.

스크린샷 2021-12-20 오전 10 33 48

반응형