IntelliJ IDEA를 사용하다가 개발업무를 거의 손놓다시피 하다보니 라이센스를 연장하지 못하게 되었고 주로 Local에서 VScode를 사용하고 있다. 현재 부서와 업무도 바뀌었고 워낙 고가다보니 IDE를 부서비로 구매하도 어렵다. 뭐 얼마나 한다고 말할수도 있겠지만 업무특성상 개발툴을 사달라고 할수 없고 최근 크롬북이나 아이패드 프로같은 태블릿을 가지고 다니시는 분들도 많고 단순 필기나 메모가 아닌 온라인 환경에서 블로깅 포스팅 정도는 할수 있다는 가정으로 Web IDE를 구성하는 포스팅을 시작해본다.
이번 포스팅을 쓰기 시작하면서 2017년 AWS re;invent에선가 Cloud9 제품이 출시되어서 Lambda에서 사용했던 장면이 갑자기 떠올랐다. Cloud 9은 https://github.com/c9/core를 기반으로 instance를 띄는것을 기본으로 한다. Lambda의 기본 에디터도 나쁘진 않지만 Cloud9에서 강조하는 부분은 코드 협업이다.
AWS에서 서비스로 출시되기 이전에도 Dockerhub에서도 종종 확인할수 있었지만 현재는 찾아보기 어렵다.
국내에는 Cloud 형태로 GoormIDE 제품이 있다.
Free 에디션도 있으니 따로 확인해보면 된다. (응원합니다!)
실제 사용을 해보면 아직 버그가 많다. 애드온이나 플러그인 설치시 제대로 동작을 하지 않는 경우도 있었고
git-sync 프로젝트와 연동을 통해 실제 gitOPS를 구현해보고자 하였으나 배포후에 mount된 repository volume에 변경사항이 발생시 갑자기 UI가 먹통이 되는 경우가 발생하기도 하였다. Kubernetes플랫폼을 개발자에게 PaaS형태로 제공하는 경우 webIDE의 좋은 옵션이 될수 있을것 같다.
K3s는 Rancher Lab에서 최소자원을 사용하는 Kubernetes 클러스터 구성을 위한 솔루션으로 시작되었고 2019년 3월 12일 현재 0.2버전이 릴리즈된 상태이다. 바이너리 전체가 40mb가 되지 않고 설치가 쉽다는 점에서 최근 트위터 상에서 이슈가 되고 있는 프로젝트라고 할 수 있다.
주로 Edge, IoT 등 저전력, 저사양 기반 ARM계열 컴퓨팅에 최적화 되어 있고 실제 실험적이긴 하지만 간단한 기능이나 baremetal 기반 클러스터 테스트를 집에서 해보기에는 딱 좋은 프로젝트라 할 수 있다. 이미 vSphere, OpenStack기반으로 테스트는 차고 넘치게 해봤지만 일단 물리적인 케이스부터 보고나면 하드웨어를 좋아하는 사람들에게는 아주 재미있는 장난감이 아닐수 없을 것이다.
K3s Github 상세 설명에 보면 Cloud Provider, Storage Plugin은 제거하였고 default 저장소가 etcd가 아닌 sqlite3으로 되어있다고 한다.
micro SDHC 4ea
16GB로도 충분하지만 삼성전자 micro SDHC CLASS10 UHS-I EVO (32GB), 4ea를 오픈마켓에서 사게되면 배송료 포함해서 8,500원 * 4ea = 34,000원에 구매가 가능하다. 오픈마켓에서는 개당 배송료를 내야한다. 하지만 쿠팡에서는 2ea를 로켓배송으로 15,380원에 구매가 가능하므로 약 31,000원에 4개를 구매할수 있다.
멀티충전기
1만원대 후반에서 2만원 초반이면 6포트 충전기를 구매할수 있는데 구매했던 가장 큰 기준은 Pi 4대를 동시에 2.5A 전류를 안정적으로 공급하려면 최대 10A를 지원하는 멀티 충전기를 사야했었고 4-5포트 짜리 충전기들은 대부분 최대 전류가 8A로 충족하지 못해 4포트만 사용하더라도 안정적인 전류 공급을 위해 6포트 충전기로 선택하였다.
쿠팡 로켓배송 - 포*지 가정용 6포트 급속 멀티 충전기, 22,900원
micro 5pin 20cm 2.4A 지원 케이블 4ea
Pi 권장 전류가 2.5A라고 했지만 2.4A, 3A 짜리중에 저렴한 2.4A 지원 숏케이블로 구매하였다.
오픈마켓에서 배송료 포함, 7800원
UTP Cat5e 30cm 케이블 4ea
그냥 제일싼걸로 오픈마켓에서 배송료 포함 4,100원에 구매하였다.
기가비트 지원되는 5포트 이상 스위치 허브(공유기)
집에 있던 공유기 활용 (iptime A1004) 하였지만 최저 5포트 이상 스위치 허브중 제일 싼 모델은 16,000원대로 가격 형성중이다.
실제 위 스펙으로 대충 구매를 진행하게 되면 18.4 + 3.3 + 3.1 + 2.3 + 0.8 + 0.4 + 1.6 = 29.9만원 정도 소요가 될 것으로 예상된다. 집에 굴러다는 부품이나 충전기, 케이블, SD카드들을 활용하면 25만원 이내로도 충분히 가능하다.
Mac에서는 /Volumes/boot에 마운트가 된다. OS마다 다르지만 Linux에서는 /mnt/boot, Windows에서는 boot 로 마운트가 된다.
SSH Service 자동 활성화를 위해 위 OS별 mount된 root 경로에 ssh 빈 파일을 생성하게 되면 reboot이후에 SSH 접속이 가능해진다.
$ sudo touch /Volumes/boot/ssh
또한 container 사용을 위해 root경로의 cmdline.txt 파일 마지막에 cgroup 설정을 추가한다.
cgroup_memory=1 cgroup_enable=memory
SD카드를 만들고 각각의 Pi에 장착후에 UTP케이블과 전원을 모두 연결한다.
부팅이 완료되면 default id/pass 인 pi/raspberry로 로그인 하고 sudo raspi-config 를 통해 패스워드 변경, hostname 설정, GPU memory split 설정 등을 완료하자.
나중에는 PXE booting 및 ansible 자동화로 구현하면 무인환경 설치가 가능할것 같다. (Edge Computing)
┌───────────────────┤ Raspberry Pi Software Configuration Tool (raspi-config) ├────────────────────┐ │ │ │ 1 Change User Password Change password for the current user │ │ 2 Network Options Configure network settings │ │ 3 Boot Options Configure options for start-up │ │ 4 Localisation Options Set up language and regional settings to match your location │ │ 5 Interfacing Options Configure connections to peripherals │ │ 6 Overclock Configure overclocking for your Pi │ │ 7 Advanced Options Configure advanced settings │ │ 8 Update Update this tool to the latest version │ │ 9 About raspi-config Information about this configuration tool │ │ │ │ │ │ │ │ <Select> <Finish> │ │ │ └──────────────────────────────────────────────────────────────────────────────────────────────────┘
완성된 클러스터를 확인한다. 외부 로컬에서 확인하려면 /etc/rancher/k3s/k3s.yaml 파일을 ~/.kube/config에 추가하면 된다. 클러스터 내부에서 kubectl 명령은 k3s 바이너리 내부에 포함되어 있으므로 sudo k3s kubectl 명령을 사용하였다.
node 상세정보를 보면 기본적으로 K8s v1.13.4, runtime은 containerd를 사용하고 있음을 알 수 있다.
$ sudo k3s kubectl get svc --all-namespaces NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE default kubernetes ClusterIP 10.43.0.1 <none> 443/TCP 21h kube-system kube-dns ClusterIP 10.43.0.10 <none> 53/UDP,53/TCP,9153/TCP 21h kube-system traefik LoadBalancer 10.43.19.160 192.168.1.14,192.168.1.15 80:32304/TCP,443:31690/TCP 21h
Rancher쪽에서도 오늘날짜(3/12)로 F5가 Nginx를 인수하는것을 예견했던 것일까?
Service를 확인하면 traefik이 기본으로 되어있다. 아래처럼 기본적으로 loadbalancer로 활용되고 있는 traefik을 Helm Chart CRD를 통해 배포된것을 확인할 수 있다. 또한 얼마전 졸업한 CoreDNS도 보인다.
$ sudo k3s kubectl get pod --all-namespaces NAMESPACE NAME READY STATUS RESTARTS AGE kube-system coredns-7748f7f6df-qflx9 1/1 Running 0 21h kube-system helm-install-traefik-dqqg9 0/1 Completed 0 21h kube-system svclb-traefik-598fd65c97-4xtkf 2/2 Running 0 21h kube-system svclb-traefik-598fd65c97-vbsqv 2/2 Running 0 19h kube-system traefik-6876857645-2sqg9 1/1 Running 0 21h $ sudo k3s kubectl get crd NAME CREATED AT addons.k3s.cattle.io 2019-03-11T16:46:22Z helmcharts.k3s.cattle.io 2019-03-11T16:46:22Z listenerconfigs.k3s.cattle.io 2019-03-11T16:46:22Z
아주 적은비용(?)으로 취미삼아 k3s 클러스터를 구성해봤다.
아직 ARM계열에서 kubernetes workload를 구동하는 것은 시기상조이긴 하지만 기존에 kubeadm을 가지고 pi에 배포하는것에 비하면 설치 난이도나 자원사용량 측면에서 장점이 많은 프로젝트이다.
해외 블로그나 트위터를 보면 최근 k3s에 대한 관심도가 높아지는것을 확인할 수 있는데 단순히 취미생활만이 아니라 IoT, Edge에서의 Serverless Workload 수행이라던지 ARM 계열 최적화된 모습만으로도 충분히 가능성은 보여준것 같다.
Rancher 2.0 이후로 Kubernetes 연관된 관심도가 떨어졌었는데 엔지니어들의 관심을 끄는데는 성공한듯 하고 AWS의 Greengrass, Firecracker와 동일선상에서 봐도 견줄만한 가치가 있다고 생각된다.
위 링크에 가서 보면 알수 있지만 Hipster Shop 아래 그림처럼 10개의 Microservice로 구성되어 있고 상품을 검색 및 구매할 수있는 웹 기반 이커머스 Application으로 구성 되어있다.
각각의 서비스는 gRPC 로 통신하고 외부 사용자만 HTTP로 접근한다. 모든 서비스는 서로 다른 언어(Go, C#, Node.js, Python, Java)로 구성되어 있고 대부분의 Microservice들은 Istio service mesh 형태로 구성할수 있도록 되어있다. Skaffold를 통해 배포하고 OpenCensus라고 하는 gRPC/HTTP기반 Tracing tool을 활용하여 Google Stackdriver로 보내도록 되어있지만 Prometheus에 통합하는 방향으로 작성하기 위해서 Prometheus 기반으로 Metric을 수집하는 Fork된 데모 Application을 검색을 통해 찾을수 있었다. https://github.com/census-ecosystem/opencensus-microservices-demo
또한 수집된 데이터를 Prometheus, Stackdriver Tracing and Monitoring, DataDog, Graphite, Zipkin, Jaeger, Azure Insights 등 과 같은 백엔드 Application으로 내보낼 수 있기 때문에 개발자, 운영자 측면에서 좋은 선택사항이 될 수 있다.
Microservice와 같은 분산 시스템에서 개발자/운영자 관점의 가장 중요한 미션은 각각의 수행되는 서비스들의 실행 시간을 확인하고 상호 API간 통신이 얼마나 걸리는지를 확인하고 Span(아래 그림참조)에서 가장 지연이 발생하는 서비스를 빨리 찾아내 확인하고 조치하는 것이라 할 수 있다.
OpenCensus는 주로 두가지 기능으로 활용된다.
첫번째는 Metric 수집이고 두번째는 Tracing 기능이다.
Log같은 경우 현재 미지원이지만 다음 메이저 릴리즈에 추가될 예정이라고 하니 조금더 지켜보면 좋을것 같다.
Metrics
데이터베이스 및 API의 응답시간, 요청 content length, open file descriptor 수와 같이 추적하고자하는 정량 데이터를 말한다. Metric 을 시각화해서 보면 응용 프로그램 및 서비스의 성능과 품질을 측정하는 데 도움이 될 수 있다. 예를 들면 요청 응답시간의 평균값이나 cache hit/miss 수와 같은 것들이 될 수 있다.
Traces
서비스 요청에 대한 애플리케이션 또는 서비스 구조를 확인할수 있고 모든 서비스 간 데이터 흐름을 시각화하여 아키텍처상의 병목 현상을 파악하는 데 도움이 된다.
위에서 언급했던 내용처럼 GCP에서 작성한 Hipster Shop Demo는 minikube 및 GCP 데모로 되어있고 코드안에 기본 Metric 설정이 Stackdriver으로 되어있어 Prometheus Exporter 적용을 하려면 코드 수정이 필요하기 때문에 Prometheus기반으로 작성된 Forked Repo를 살펴보기로 하였다.
$ git clone https://github.com/census-ecosystem/opencensus-microservices-demo.git $ cd opencensus-microservices-demo
내부 구조를 살펴보면 기본적으로 skaffold를 활용하여 배포를 진행을 하는 것을 알수있다. skaffold는 로컬에서 Kubernetes 기반 어플리케이션 개발과 배포(CD)를 빠르게 도와주는 CLI tool이다. 소스코드의 변화를 감지하여 build, registry push/tagging, deploy까지 자동으로 할 수 있는 로컬 기반 도구이다.
skaffold dev는 로컬 환경의 반복적인 개발에 활용하고 실제 배포는 CI Process에서 skaffold run을 통해 배포를 진행할 수 있다.
기본적으로 구성을 하고자 하는 내용은 helm처럼 template 파일을 사용하게 되는데 프로젝트 root에 skaffold.yaml 에 build를 위한 image name, tag, src 위치등 기본적인 내용을 기재한다. 파일내용을 살펴보면 build에 관련된 내용들을 작성하고 deploy할 manifests의 위치까지 지정하도록 되어있다. 로컬환경에서 확인을 위해 grafana, prometheus, jaeger가 추가된 것을 확인할 수 있다.
exporter 등록(Jaeger Tracing 및 Prometheus exporter)
예시처럼 각각의 서비스에 jaeger와 prometheus exporter Endpoint를 쉽게 등록할수 있다.
또한 initTracing() 에서는 데모를 위해 trace.AlwaysSample()을 사용하였다. 실제 운영환경에서는 다음 링크를 참고해서 사용하는 것을 권고하고 있다.
... funcinitJaegerTracing(log logrus.FieldLogger){ // Register the Jaeger exporter to be able to retrieve // the collected spans. exporter, err := jaeger.NewExporter(jaeger.Options{ Endpoint:"http://jaeger:14268", Process: jaeger.Process{ ServiceName:"frontend", }, }) if err !=nil{ log.Fatal(err) } trace.RegisterExporter(exporter) } funcinitTracing(log logrus.FieldLogger){ // This is a demo app with low QPS. trace.AlwaysSample() is used here // to make sure traces are available for observation and analysis. // In a production environment or high QPS setup please use // trace.ProbabilitySampler set at the desired probability. trace.ApplyConfig(trace.Config{ DefaultSampler: trace.AlwaysSample(), }) initJaegerTracing(log) } funcinitPrometheusStatsExporter(log logrus.FieldLogger)*prometheus.Exporter { exporter, err := prometheus.NewExporter(prometheus.Options{}) if err !=nil{ log.Fatal("error registering prometheus exporter") returnnil } view.RegisterExporter(exporter) return exporter } funcstartPrometheusExporter(log logrus.FieldLogger, exporter *prometheus.Exporter){ addr :=":9090" log.Infof("starting prometheus server at %s", addr) http.Handle("/metrics", exporter) log.Fatal(http.ListenAndServe(addr,nil)) } ...
minikube에 Hipster Shop Demo를 배포한다. 단순하게 skaffold run 명령으로 진행하면 된다.
$ skaffold run
현재 사용중인 2018 Macbook Pro(3.1 GHz Intel Core i7, 16GB) 상의 Docker기반 minikube 환경으로도 배포를 하였는데 시간이 꽤 소요되었다.(20분이상)
코드를 실시간으로 수정하고 빌드, 배포되는 것은 skaffold dev 명령으로 확인할 수 있다. 진행되는 과정을 보면 draft.sh 프로젝트와도 꽤 유사하다고 볼 수 있다.
에러없이 run이 실행되고 난후 minikube에 배포된 pod와 service를 확인한다. 중간에 loadgenerator가 init인 이유는 minikube 자원이 부족해서 발생하는 현상이다.
OpenCensus 기반으로 개발자가 코드를 작성하고 Microservice를 minikube에서 배포하고 Prometheus, Jaeger Exporter 연동을 통해 시스템뿐만이 아닌 Application기반 Metrics/Stats을 수집하고 개발자가 작성한 코드를 직접 Tracing하는 간단한 데모를 진행하였다. (Istio를 포함해서 Public환경에 배포해봐도 좋은 공부가 될 것 같다)
향후 OpenMetric과 Opencensus가 실제 개발자 기반으로 활성화되고 적용이 된다면 Telemetric 측면에서 많은 Use-Case가 도출될 수 있을것 같다.
위에서 언급했듯이 Prometheus기반 Kubernetes 클러스터를 운영하고 있는 팀의 경우 개발자의 작성 코드를 최소화할 수 있는 도구로서 충분히 활용될 수 있어 보인다.
꼭 Cloud Native 기반 Web 개발이 아니더라도 기존 공장, 금융, 병원 등 의 IoT나 센서/설비를 위한 비즈니스에도 Backend로서 확장성있는 도구로서 활용이 될 수 있을것 같다.
Knative는 앞에서도 몇번 언급하였지만 기본적으로 Routing을 사용하여 외부에 노출할 서비스들에 대한 HTTP Endpoint를 제공한다. 어떻게 보면 기본적으로 API Gateway 역할을 하기도 하고 Ingress 역할을 하기도 한다. 보통 Service mesh인 Istio를 사용하여 ingress를 구현하는것이 당연하다고 생각하기도 하지만 Istio의 모든 기능이 Knative에 필요하지는 않고 설치되는것 자체가 리소스 소모가 꽤 된다는것은 설치 해본사람은 알고 있을것이다.
Knative에서는 앞선 Knative 관련 포스팅에서도 설명했듯이 Automatic scaling up and down to zero 특성을 가지고 있기에 Pod가 최초 실행되어있지 않은 상태에서 트래픽이 들어오게 되면 Knative Serving Activator에 의해서 Pod가 없는 Revision을 확인하고 Cold Start 형태로 프로비저닝하게 된다. 나는 이게 진정한 서버리스라고 생각하지만 주변에 반박하시는 분들도 간혹 있다.
이후 Pod가 Warm 상태가 되고 나면 Istio Route(Ingress Gateway)를 통해 트래픽이 Pod로 전달되어 통신이 이뤄지게 된다.
현재 Knative는 현재 Ingress Gateway 의존성을 가지고 있고 Envoy기반 Service Mesh인 Istio, Envoy기반 API Gateway인 Gloo 두가지 옵션으로 Ingress 구현이 가능하다.
Gloo는 Kubernetes-native ingress controller이자 Next Generation API Gateway 를 위해 시작된 프로젝트이다. 실제 Redhat에서 Openshift기반 Microservice 및 Istio 개발업무를 하다가 최근에 solo.io의 CTO로 이직한 Christian Posta가 밀고 있는 프로젝트이기도 하다.
Gloo는 Envoy Proxy 기반으로 동작하며
기존 Legacy부터 Container서비스, FaaS(AWS Lambda, Azure Functions, GCP Functions)영역의 Application들을 REST, gRPC, SOAP, Web Socker기반으로 Aggregate 해서 Function 기반 추상화를 구현해 주는 오픈소스 프로젝트라 정의 할 수 있다.
Istio의 Ingress기능외의 여러가지 부가 기능(Telemetry, Security, Policy Enforcement)들은 Knative에서는 필요로 하지 않는다.
Knative API Gateway 로서 Istio가 아닌 Gloo가 조금더 경량화된 대안으로 결정되었고 Gloo를 통해 Knative 설치가 가능하게 되었다. 단, Knative Eventing 컴포넌트는 현재 지원하지 않는다고 한다.
$ curl -sL https://run.solo.io/gloo/install | sh Attempting to download glooctl version v0.8.1 Downloading glooctl-darwin-amd64... Download complete!, validating checksum... Checksum valid. Gloo was successfully installed 🎉 Add the gloo CLI to your path with: export PATH=$HOME/.gloo/bin:$PATH Now run: glooctl install gateway # install gloo's function gateway functionality into the 'gloo-system' namespace glooctl install ingress # install very basic Kubernetes Ingress support with Gloo into namespace gloo-system glooctl install knative # install Knative serving with Gloo configured as the default cluster ingress Please see visit the Gloo Installation guides for more: https://gloo.solo.io/installation/
Gloo는 Knative ClusterIngress CRD를 기반으로 동작하는 Istio의 대안으로서 가능성을 보여주고 있다. 이외에도 The Service Mesh Orchestration Platform SuperGloo, Debugger for microservices Squash 등 다양한 Mesh Layer기반의 오픈소스들을 확인할수 있다. 또다른 스쳐지나갈수도 있는 오픈소스일수도 있겠지만 현재 개발되는 로드맵(https://www.solo.io/)을 보면 Knative가 고도화되는 여정에 같이 가는 모습을 확인할 수 있다.
next-generation API Gateway로서 다양한 프로토콜을 지원하기 때문에 (HTTP1, HTTP2, gRPC, REST/OpenAPISpec, SOAP, WebSockets, Lambda/Cloud Functions) 더욱더 Microservices 및 Serverless Workload를 수행하기에 더욱 적합한 오픈소스로 보인다.
Route는 사용자 서비스(Code와 Configuration의 Revision정보)의 네트워크 Endpoint를 제공한다. kubernetes namespace는 여러개의 Route를 가질수 있다. Route는 하나 이상의 Revisions을 가지면서 수명이 길고 안정적인 HTTP Endpoint를 제공한다. 기본구성은 Route 객체가 Configuration에 의해 생성된 최신의 Revision으로 트래픽을 자동으로 지정한다. 조금더 복잡한 경우로는 istio의 기능을 활용하여 트래픽을 백분율 기준으로 Route를 지정할 수 있다.
Revision은 Code와 Configuration의 불변의 스냅샷이다. 하나의 Revision은 컨테이너 이미지를 참조하고 선택적으로 Build를 참조할 수 있다. Revision은 Configuration이 업데이트 시 생성된다. Route를 통해 http주소 지정이 불가능한 Revision은 폐기 되고 관련된 kubernetes 리소스가 삭제가 된다. 시간이 지남에 따라 Configuration이 생성한 Revision 히스토리가 제공되고 사용자는 이전 Revision로 쉽게 롤백 할 수 있다.
Configuration은 최신의 Revision상태를 설명하고, 생성하고, 원하는 상태가 갱신될때 Revision의 상태를 추적한다. Configuration은 Build를 참조하여 소스(git repo 또는 archive)를 컨테이너로 변환하는 방법에 대한 가이드가 포함되어 있거나 단순히 컨테이너 이미지 및 수정에서 필요한 메타 데이터 만 참조 할 수 있다.
$ kubectl get nodes NAME STATUS ROLES AGE VERSION gke-knative-default-pool-d1a39347-5m5t Ready <none> 1m v1.11.7-gke.4 gke-knative-default-pool-d1a39347-l6zh Ready <none> 1m v1.11.7-gke.4 gke-knative-default-pool-d1a39347-qv5r Ready <none> 1m v1.11.7-gke.4 $ kubectl create clusterrolebinding cluster-admin-binding \ --clusterrole=cluster-admin \ --user=$(gcloud config get-value core/account) Your active configuration is: [cloudshell-4728] clusterrolebinding.rbac.authorization.k8s.io "cluster-admin-binding" created
설치한 knctl로 Knative 배포를 진행한다. 설치되는 내용을 지켜보고 있으면 istio를 먼저 배포하고 그다음에 Knative를 설치하는 것을 확인할 수 있다. 배포되는 모듈들의 상태를 하나하나 체크해서 배포하기 때문에 설치상에 과정들을 확인할 수 있다.
$ knctl install --exclude-monitoring
테스트를 위한 namespace hello-test를 생성한다.
$ kubectl create namespace hello-test namespace "hello-test" created
knctl deploy 명령으로 최초 revision을 배포한다.
아래 결과를 보면 hello-00001 이라고 하는 최초의 revision을 작성하기 때문에 latest tag를 달고 배포를 하게 된다.
$ knctl deploy \ --namespace hello-test \ --service hello \ --image gcr.io/knative-samples/helloworld-go \ --env TARGET=Rev1 Name hello Waiting for new revision to be created... Tagging new revision 'hello-00001' as 'latest' Tagging new revision 'hello-00001' as 'previous' Annotating new revision 'hello-00001' Waiting for new revision 'hello-00001' to be ready for up to 5m0s (logs below)... hello-00001 > hello-00001-deployment-5cdbfc9bc9-hks6t | 2019/02/17 22:27:50 Hello world sample started. Revision 'hello-00001' became ready Continuing to watch logs for 5s before exiting Succeeded
kubectl get svc knative-ingressgateway -n istio-system NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE knative-ingressgateway LoadBalancer 10.63.253.209 34.***.***.248 80:32380/TCP,443:32390/TCP,31400:32400/TCP,15011:30082/TCP,8060:31125/TCP,853:32009/TCP,15030:31102/TCP,15031:31631/TCP 6h
위처럼 Knative가 프로비저닝 되면서 ingress-gateway가 하나 생성이 되어있는 것을 확인할 수 있고 knctl로도 ingress를 확인이 가능하다.
$ knctl ingress list Ingresses Name Addresses Ports Age knative-ingressgateway 34.***.***.248 80 6h 443 31400 15011 8060 853 15030 15031 1 ingresses Succeeded
Domain이 별도로 없기 때문에 Knative는 내부적으로 example.com이라고 하는 기본 domain을 사용한다. 그래서 실제 knctl curl 명령은 내부적으로 hello.hello-test.example.com으로 curl을 실행하게 되고 해당 결과를 아래와 같이 확인할 수 있다.
kubernetes node가 3개이므로 3개의 pod가 생성된 것을 확인할 수 있다. 일정시간(default:5분)이 지나면 zero to scale 관점에서 pod가 종료되므로 다시 확인할때는 다시 curl 명령을 날리게 되면 다시 pod가 올라오게 된다. 해당 개념은 FaaS또는 AWS Lambda에서 Cold-Start와 동일한 것이라 볼 수 있다.
이번에는 revision을 추가해보자. TARGET environment 변수를 Rev2로 수정하고 배포를 한다.
기존 hello-00002 revision이 최신 revision으로 갱신되어 배포가 되는것을 확인할 수 있다.
$ knctl deploy --service hello \ --image gcr.io/knative-samples/helloworld-go \ --env TARGET=Rev2 Name hello Waiting for new revision (after revision 'hello-00001') to be created... Tagging new revision 'hello-00002' as 'latest' Tagging older revision 'hello-00001' as 'previous' Annotating new revision 'hello-00002' Waiting for new revision 'hello-00002' to be ready for up to 5m0s (logs below)... hello-00002 > hello-00002-deployment-6cf86bbfc7-sblz9 | 2019/02/17 23:25:43 Hello world sample started. Revision 'hello-00002' became ready Continuing to watch logs for 5s before exiting Succeeded
신규 revision 서비스를 추가된것을 확인할 수 있다. 마찬가지로 몇초간의 Cold-Start delay가 발생할 수도 있다.
Blue/Green Deploy는 knctl rollout 명령으로 수행할수 있다.
rollout 할때 --managed-route=false 옵션을 줘야 특정 비율로 routing이 가능하다.
아래 예시는 TARGET environment 변수를 blue, green으로 바꿔가면서 배포를 진행하였다.
$ knctl deploy --service hello \ --image gcr.io/knative-samples/helloworld-go \ --env TARGET=blue \ --managed-route=false Name hello Waiting for new revision (after revision 'hello-00002') to be created... Tagging new revision 'hello-00003' as 'latest' Tagging older revision 'hello-00002' as 'previous' Annotating new revision 'hello-00003' Waiting for new revision 'hello-00003' to be ready for up to 5m0s (logs below)... Revision 'hello-00003' became ready Continuing to watch logs for 5s before exiting hello-00003 > hello-00003-deployment-99478dcc5-jf267 | 2019/02/17 23:48:20 Hello world sample started. Succeeded
revision list를 확인하면 아래와 같이 latest로 Traffic 전체가 routing 되는 것을 확인할 수 있다.
$ knctl revision list --service hello Revisions for service 'hello' Name Tags Annotations Conditions Age Traffic hello-00005 latest - 4 OK / 4 44s 100% -> hello.hello-test.knative.skcloud.io hello-00004 previous - 4 OK / 4 2m - hello-00003 - - 1 OK / 4 5m - hello-00002 - - 1 OK / 4 28m - hello-00001 - - 1 OK / 4 4h - 5 revisions Succeeded
이후에 rollout을 통해 previous로 90%, latest로 10%로 변경을 하면 즉시 반영이 되고 실제 트래픽도 분산되어 들어온다. %가 낮은 쪽으로 routing이 될 경우 Cold-Start가 발생하게 되면 delay는 발생하게 된다.
$ knctl rollout --route hello -p hello:latest=10% -p hello:previous=90% Succeeded $ knctl revision list Revisions Service Name Tags Annotations Conditions Age Traffic hello hello-00005 latest - 2 OK / 4 1h 10% -> hello.hello-test.knative.skcloud.io ~ hello-00004 previous - 2 OK / 4 1h 90% -> hello.hello-test.knative.skcloud.io ~ hello-00003 - - 1 OK / 4 1h - ~ hello-00002 - - 1 OK / 4 1h - ~ hello-00001 - - 1 OK / 4 5h - 5 revisions Succeeded
간단하게 curl 반복문을 작성하여 돌려보자.
#!/bin/sh while true do curl -sS --max-time 3 http://hello.hello-test.knative.skcloud.io/ done
간단하게 위 sh을 돌리면 아래와 같이 Cold-Start delay가 발생할때 time out이 발생하고 이후 green revision으로 접속이 되는것을 볼 수 있다.
$ ./test.sh curl: (28) Operation timed out after 3002 milliseconds with 0 bytes received Hello blue! Hello blue! Hello blue! Hello blue! Hello blue! curl: (28) Operation timed out after 3003 milliseconds with 0 bytes received Hello blue! Hello blue! Hello blue! Hello blue! Hello blue! Hello blue! Hello green! Hello blue! Hello blue! Hello blue!
지금까지 knctl을 사용하여 간단하게 knative를 배포하고 custom domain을 연결하여 blue-green 배포까지 해봤다.
이외에도 Knative Build를 활용하여 Docker image 작업을 하거나 서비스 카탈로그 등을 연동하여 외부 DBaaS를 연동하는 use-case등을 찾아볼수 있다.
아직 초기 단계이지만 Knative는 istio와 함께 IBM, Google, Pivotal등 global player들의 차세대 오픈소스로 부상하고 있다고 볼 수 있다.
Zero to scale 이라는 슬로건아래 Serverless, FaaS 사상을 기반으로 build, serving, event, routing이라고 하는 Cloud Computing 추상화의 끝판으로 진화하고 있다. 앞으로 어떤 모습으로 진화될지 궁금하고 다음번에는 MQ나 Pub/sub를 연동하거나 멀티 클라우드 환경에서 동작하는 모습을 보여주는 것도 좋을것 같다. 희망사항이지만 올해 OpenInfraDay나 Kubernetes Day Korea 행사에서 Hands-on을 진행해보는것도 좋지 않을까?