이번에는 Knative를 EKS에 구성해보려고 한다. 4월은 발표 및 여러가지 업무로 인해서 포스팅을 할 시간이 부족했지만 5월부터 조금씩 여유가 생겨서 더 바빠지기전에 좀 써보려고 한다. 사실 Facebook @최용호님께서 한번 해보는것도 좋겠다고 하셔서 테스트를 진행하였다.
제목만 보면 Lambda나 ECS, Batch 서비스가 있는데 왜 이걸 써야하지? 라는 생각부터 하는 사람도 있을것 같다. 하지만 이전 포스팅들과 발표에서도 여러번 이야기 한것처럼 Knative는 간단하게 서버리스 워크로드를 빌드, 배포, 관리하기 위한 Kubernetes기반 FaaS플랫폼이고 현재 CNCF Landscape에서 가장 빠른 속도로 개발되고 있는 오픈소스 프로젝트 중 하나이다.
$ kubectl get nodes NAME STATUS ROLES AGE VERSION ip-192-168-24-168.ap-northeast-2.compute.internal Ready <none> 2m v1.11.9 ip-192-168-78-204.ap-northeast-2.compute.internal Ready <none> 2m v1.11.9
Istio injection을 하기 위해 배포할 defaults namespace 전체에 Labeling을 한다.
$ kubectl label namespace default istio-injection=enabled namespace/default labeled $ kubectl get namespaces --show-labels NAME STATUS AGE LABELS default Active 43m istio-injection=enabled istio-system Active 27m istio-injection=disabled kube-public Active 43m <none> kube-system Active 43m <none>
미리 Dockerhub에서 hello-python repository(docker.io/ddiiwoong/hello-python)를 생성한다.
그리고 위에서 생성한 build-bot 계정과 image tag hello-python정보를 Build template에 작성하여 배포한다.
아래 Knative Build 과정은 kaniko executor를 사용하여 다음과 같은 과정을 수행한다.
spec.source 에서 Source Clone (git)를 수행하고 이후
spec.steps 에서 Docker Build, Tag, Registry Login, Push를 수행한다.
kubectl get svc istio-ingressgateway --namespace istio-system NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE istio-ingressgateway LoadBalancer 10.100.208.80 a220723d475df11e980220a02e220b34-2021915778.ap-northeast-2.elb.amazonaws.com 80:31581/TCP,443:31490/TCP,31400:30367/TCP,15011:32495/TCP,8060:31418/TCP,853:30310/TCP,15030:32405/TCP,15031:31410/TCP 13h
위와 같이 AWS LoadBalancer로 배포면 ALB가 자동으로 생성되므로 추후 eksctl로 클러스터를 삭제하기 전에 반드시 LoadBalancer 형태로 배포된 서비스를 삭제하고 진행해야 한다.
Knative Service를 확인한다.
$ kubectl get ksvc NAME DOMAIN LATESTCREATED LATESTREADY READY REASON helloworld-python helloworld-python.default.example.com helloworld-python-4rw95 helloworld-python-4rw95 True
위에서 얻은 두가지 정보(LoadBalancer, Domain)로 생성된 app을 테스트한다.
Knative는 내부적으로 example.com이라고 하는 기본 domain을 사용하므로 내부적으로는 helloworld-python.default.example.com으로 curl을 실행하게 된다.
$ curl -H "Host:helloworld-python.default.example.com" http://a220723d475df11e980220a02e220b34-2021915778.ap-northeast-2.elb.amazonaws.com Hello World: Python Sample v1 with Knative on EKS!
Cold Start(default timeout 5분) 때문에 잠시 응답이 늦어질 수도 있지만(2-5초) 잠시 기다리면 위처럼 결과를 확인할 수 있다.
위에서도 잠깐 언급했지만 Lambda나 ECS, Batch 서비스가 있는데 Knative on EKS 를 구지 왜 하느냐라고 궁금해하는 분들이 계실지도 모른다. 하지만 다들 아래와 같은 고민을 해봤을거라 생각한다.
컨테이너와 Kubernetes가 DevOps도구로서의 표준이 되어가는 시대에 Lambda를 쓸지 오픈소스를 쓸지에 대한 고민은 결국 이식성과 벤더 종속성을 제거하고 운영효율화 측면에서 그 답을 찾을수 있을것 같다.
현재 몸담고 있는 최근 프로젝트에서 Lambda, ECS, Batch 등을 사용하는 경우가 많아졌는데 실제 엔터프라이즈에서 정해진 자원내에서 정해진 일을 할때는 매니지드 서비스가 적합하다고 생각한다. 하지만 On-Premise 또는 그에 준하는 Kubernetes 클러스터를 운영하는 조직에서는 Knative를 사용하여 컨테이너 기반 서비리스 워크로드를 구현하는 것이 향후 Hybrid 관점에서 확장성과 벤더 종속성을 제거하는데 큰 도움이 될것이라 생각한다.
조금씩 Kubernetes 및 생태계 Learning에 대한 피로도가 증가하고 있고 Hype Driven Development(설레발 주도개발)가 되는것 같아서 아쉬운 부분은 있지만 현재 가장 핫한 기술이고 관심도가 높기 때문에 배워두면 언젠가는 써먹게 될거라 확신한다.
다시한번 Conference driven development(architecture)가 되지 않도록 자중하고 Loudest Guy가 되지 않도록 조심해야할 것 같다.
Amazon EKS (Elastic Container Service for Kubernetes)
Kubernetes Managed Service인 Amazon EKS가 2018년 7월 출시되고 2019년 1월 정식으로 서울리전에 출시되었다. 개인적으로 완전관리형 Kubernetes 출시가 늦어져서 AWS 행보가 다소 늦다고 생각은 했으나 ALB와 VPC연동, 여러가지 기존 OpenSource와의 연결고리를 배제하고 자체 Managed서비스와 연동할것들이 많기 때문에 당연히 타사에 비해 늦어진걸로 보인다. 언제나 그랬지만 오픈소스를 받아들이는 느낌이 아니라 뭔가 완성된 제품을 쓰는 느낌(?)이다. 물론 불편한 부분과 감수해야할 내용들은 조금 있지만 기존 AWS 충성 User에게 호응을 얻을수 있기 때문이 아닐까라는 생각을 해보면서 포스팅을 시작하려고 한다.
오픈소스가 아닌 Managed서비스에 대한 리뷰는 처음이지만 4월 10일 AWS판교소모임 발표도 있고, 실제 고려중인 아키텍처에 포함이 되어야 하는 EKS에 대해서 살펴보고 eskworkshop 튜토리얼을 실행해보면서 다른 관리형 Kubernetes 서비스들에 비해 어떤 사항을 좀더 고민해야 하는지 정리해보고 넘어가면 좋을듯 하다.
Amazon EKS는 IAM을 사용하여 Kubernetes용 AWS IAM Authenticator를 통해 Kubernetes 클러스터에 인증을 제공한다. Go(버전 1.7이상)가 설치되어 있으면 아래와 같이 진행하면 된다.
$ go get -u -v github.com/kubernetes-sigs/aws-iam-authenticator/cmd/aws-iam-authenticator $ sudomv ~/go/bin/aws-iam-authenticator /usr/local/bin/aws-iam-authenticator
kubectl, aws-iam-authenticator, eksctl, AWS 자격증명 환경까지 구성되어 있으면 바로 배포가 가능하다.
$ eksctl create cluster --name=eksworkshop-eksctl --nodes=3 --node-ami=auto [ℹ] using region ap-northeast-2 [ℹ] setting availability zones to [ap-northeast-2a ap-northeast-2c ap-northeast-2a] [ℹ] subnets for ap-northeast-2a - public:192.168.0.0/19 private:192.168.96.0/19 [ℹ] subnets for ap-northeast-2c - public:192.168.32.0/19 private:192.168.128.0/19 [ℹ] subnets for ap-northeast-2a - public:192.168.64.0/19 private:192.168.160.0/19 [ℹ] nodegroup "ng-cfb3cb01" will use "ami-0c7972077aa002104"[AmazonLinux2/1.11] [ℹ] creating EKS cluster "eksworkshop-eksctl"in"ap-northeast-2" region [ℹ] will create 2 separate CloudFormation stacks for cluster itself and the initial nodegroup [ℹ]if you encounter any issues, check CloudFormation console or try 'eksctl utils describe-stacks --region=ap-northeast-2 --name=eksworkshop-eksctl' [ℹ] creating cluster stack "eksctl-eksworkshop-eksctl-cluster" [ℹ] creating nodegroup stack "eksctl-eksworkshop-eksctl-nodegroup-ng-cfb3cb01" [ℹ] --nodes-min=2 was set automatically [ℹ] --nodes-max=2 was set automatically [✔] all EKS cluster resource for"eksworkshop-eksctl" had been created [✔] saved kubeconfig as "/Users/ddii/.kube/config" [ℹ] nodegroup "ng-cfb3cb01" has 0 node(s) [ℹ] waiting for at least 2 node(s) to become ready in"ng-cfb3cb01" [ℹ] nodegroup "ng-cfb3cb01" has 2 node(s) [ℹ]node"ip-192-168-42-42.ap-northeast-2.compute.internal" is ready [ℹ]node"ip-192-168-66-165.ap-northeast-2.compute.internal" is ready [ℹ] kubectl command should work with "/Users/ddii/.kube/config", try 'kubectl get nodes' [✔] EKS cluster "eksworkshop-eksctl"in"ap-northeast-2" region is ready
서울리전(ap-northeast-2)기준 약 15-20분이 소요되며 eksctl 기본 설정값은 다음과 같다.
기존에 관리하는 VPC subnet정보 및 AutoScaling, AZ(availabilityZones)설정, nodegroup 관리, node Instance에 preBootstrapCommand등을 아래 예시와 같이 미리 작성하면 GitOps측면에서 활용도가 더욱 높아질수 있다.
# An advanced example of ClusterConfig object with customised nodegroups: --- apiVersion: eksctl.io/v1alpha4 kind: ClusterConfig metadata: name: cluster-5 region: eu-west-2 nodeGroups: -name: ng1-public instanceType: m5.xlarge minSize:2 maxSize:8 labels: nodegroup-type: frontend-workloads iam: withAddonPolicies: autoScaler:true -name: ng2-private-a instanceType: m5.large desiredCapacity:2 labels: nodegroup-type: backend-cluster-addons privateNetworking:true preBootsrapCommand: # allow docker registries to be deployed as cluster service -'echo {\"insecure-registries\": [\"172.20.0.0/16\",\"10.100.0.0/16\"]} > /etc/docker/daemon.json' -"systemctl restart docker" -name: ng3-private-b instanceType: c3.8xlarge desiredCapacity:4 labels: nodegroup-type: very-special-science-workloads privateNetworking:true availabilityZones:["eu-west-2a"]# use single AZ to optimise data transfer between isntances preBootstrapCommand: # disable hyperthreading -"for n in $(cat /sys/devices/system/cpu/cpu*/topology/thread_siblings_list | cut -s -d, -f2- | tr ',' '\n' | sort -un); do echo 0 > /sys/devices/system/cpu/cpu${n}/online; done" # cluster AZs must be set explicitly for single AZ nodegroup example to work availabilityZones:["eu-west-2a","eu-west-2b","eu-west-2c"]
그냥 localhost:8080 으로만 접속하면 구성된 클러스터 kube API list를 확인되므로 아래 경로로 접속한다.
위에서 출력된 TOKEN값으로 로그인한다. Token 세션 Timeout이 있으니 세션만료시 aws-iam-authenticator 명령을 통해 갱신값을 입력하면 된다.
위에서 외부접속을 위해 LoadBalancer를 수동으로 설정하였으므로 EC2 - Load Balancer서 프로비저닝된 ALB를 삭제하고 진행해야 한다.
클러스터에서 실행 중인 모든 서비스를 다시 확인하고 EXTERNAL-IP값과 연결된 모든 서비스를 삭제한다.
$ kubectl get svc --all-namespaces $ kubectl delete svc front-end
ALB와 VPC 삭제가 완료된것을 확인하고 클러스터를 삭제하자.
$ eksctl delete cluster --name=eksworkshop-eksctl [ℹ] deleting EKS cluster "eksworkshop-eksctl" [ℹ] will delete stack "eksctl-eksworkshop-eksctl-nodegroup-ng-3af535b7" [ℹ] waiting for stack "eksctl-eksworkshop-eksctl-nodegroup-ng-3af535b7" to get deleted [ℹ] will delete stack "eksctl-eksworkshop-eksctl-cluster" [✔] kubeconfig has been updated [✔] the following EKS cluster resource(s)for"eksworkshop-eksctl" will be deleted: cluster. If in doubt, check CloudFormation console
서울 리전(ap-northeast-2)에 EKS가 오픈되고 Production환경을 EKS로 넘어가는 기업들이 많아지고 있는건 아주 긍정적인 현상이다.
또한 엄청난 속도의 기술개발과 다양한 툴들로 Kubernetes Cluster를 구성하거나 Microservice형태의 App을 배포하는것은 점점 대중화 되어가고 있다.
실제 Production에서 구현을 하기 위해서는 보안 및 성능을 동시에 고려한 네트워크(CNI), Ingress 설정이나 전체 클러스터 퍼포먼스 측면에서의 파라미터 튜닝이 더욱 더 중요해지고 관련된 DevOps(SRE) 인력들의 중요도가 높아질것은 분명해 보인다.
EKS를 오픈소스 측면에서 고려했을때에는 예전에 페이스북이나 다른곳에서 종종 이야기 했던것처럼 AWS 고유의 Lock-in 전략을 엄청나게 고민하고 발표한듯한 생각이 한 느낌을 지울수는 없는건 사실이지만 훌륭한 제품인건 확실하고 단기간에 서비스 성장속도를 낼 수 있는 서비스라 생각한다.
Kubernetes Github에 방문하면 다양한 프로젝트들을 볼 수 있다. Kubernetes Project부터 minikube, kubeadm, kubectl, kubelet, dashboard등 필수적으로 필요하거나 많이 사용되는 프로젝트를 볼 수 있는데,
기존에 storage volume 으로 활용되던 gitrepo가 deprecated 되어서 방법을 찾다가 유사한 프로젝트를 공식 repo에서 우연히 발견하게 되었다.
git-sync는 sidecar 방식으로 git repository를 clone하는 프로젝트이다.
최초 한번 clone도 가능하고 일정한 간격으로 끌어와서 응용프로그램에 사용할 수 있고 원하는 branch, Tag 또는 특정 git hash 기반으로 pulling이 가능하다.
upstream의 repository에서 대상이 변경되었을때 다시 pulling하고, webhook기능을 추가하여 비동기성으로 POST 요청이 있을때만 git-sync를 수행할수 있기 때문에
Continuous Deployment를 간단하게 구현하는데 활용될 수 있다.
$ ssh-keygen -t rsa -b 4096 -C "ddiiwoong@gmail.com" # Start the SSH key creation process > Enter file in which the key is (/Users/you/.ssh/id_rsa): [Hit enter] > Key has comment '/Users/you/.ssh/id_rsa' > Enter new passphrase (empty for no passphrase): [Type new passphrase] > Enter same passphrase again: [One more time for luck] > Your identification has been saved with the new passphrase.
$ kubectl create secret generic git-creds \ --from-file=ssh=$HOME/.ssh/id_rsa \ --from-file=known_hosts=/tmp/known_hosts $ kubectl get secret git-creds NAME TYPE DATA AGE git-creds Opaque 2 1d
위 nginx를 배포하고 접속하면 Hello git-sync demo v1.0를 확인할 수 있다.
결국 git repo code (static html page)는 /usr/share/nginx/html 위치에 clone 되는것처럼 보이지만
실제 clone 위치를 확인해보면 symbolic link로 특정 revision dir를 가리키고 있다.
$ kubectl exec -it git-sync-demo-665c9c9ddf-6nwc4 sh Defaulting container name to nginx. Use 'kubectl describe pod/git-sync-demo-665c9c9ddf-6nwc4 -n default' to see all of the containers in this pod. / # cd /usr/share/nginx/ /usr/share/nginx # ls -al total 16 drwxrwsrwx 4 root nogroup 4096 Mar 21 06:54 . drwxr-xr-x 1 root root 4096 Mar 8 03:09 .. drwxr-sr-x 9 65533 nogroup 4096 Mar 21 06:54 .git lrwxrwxrwx 1 65533 nogroup 44 Mar 21 06:54 html -> rev-07aa36f719091d75b5665203fa5846a549e7d540 drwxr-sr-x 2 65533 nogroup 4096 Mar 21 06:54 rev-07aa36f719091d75b5665203fa5846a549e7d540 /usr/share/nginx # cat ./html/index.html <!DOCTYPE html> <html> <head> <title>Hello git-sync demo</title> </head> <body> <h1>Hello git-sync demo v1.0</h1> </body> </html>
github에 있는 위 index.html 내용을 수정하고 commit을 하게 되면 실시간으로 아래와 같이 revision 정보 및 내용이 바뀐것을 확인할수 있다.
/usr/share/nginx # ls -al total 16 drwxrwsrwx 4 root nogroup 4096 Mar 21 13:40 . drwxr-xr-x 1 root root 4096 Mar 8 03:09 .. drwxr-sr-x 9 65533 nogroup 4096 Mar 21 13:40 .git lrwxrwxrwx 1 65533 nogroup 44 Mar 21 13:40 html -> rev-b125908649135856d79c515c17decba68797a6cb drwxr-sr-x 2 65533 nogroup 4096 Mar 21 13:40 rev-b125908649135856d79c515c17decba68797a6cb /usr/share/nginx # cat ./html/index.html <!DOCTYPE html> <html> <head> <title>Hello git-sync demo</title> </head> <body> <h1>Hello git-sync demo v1.1</h1> </body> </html>
git-sync를 간단하게 테스트해봤다.
간단하게 sidecar 방식의 clone tool로서 git-sync를 활용하면 여러가지로 충분히 활용이 가능할 것이다.
포스팅을 작성하면서 떠오른 활용용도를 정리하면 아래와 같다. 어찌보면 sidecar pattern의 활용방안이라고도 볼수 있다.
CDN을 사용하지 않고 git에서 소규모로 컨텐츠를 가져올때
DBMS가 필요없을 정도의 적은 데이터를 가져올때
jekyll이나 hugo 같은 정적 사이트(블로그)의 sidecar 패턴 (GitPage처럼 markdown을 추가하고 git commit하면 바로 사이트에 반영되는 방식)
nginx, haproxy, apache와 같이 config 변경이 필요할때 webhook방식으로 설정을 변경한후 pod를 재기동하는 GitOps 구현
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의 좋은 옵션이 될수 있을것 같다.