Outsider's Dev Story

Stay Hungry. Stay Foolish. Don't Be Satisfied.
RetroTech 팟캐스트 44BITS 팟캐스트

Kubernetes 클러스터에 배포할 애플리케이션의 로컬 개발을 쉽게 해줄 Telepresence

비정기적으로 하는 인프라 스터디에서 12월부터 Programming Kubernetes를 보고 있다. 2년 전에 했던 방식과 비슷하게 이번에도 일주일에 한 번씩 1시간은 책의 진도를 나가고 한 시간은 CNCF의 프로젝트(라고 했지만, 딱히 CNCF가 아니더라도...)를 하나씩 살펴보고 공유하고 있다. 2년 전 스터디에서는 Cortex를 살펴봤다.

이번에는 Telepresence를 살펴봤다. Telepresence는 지난 회사에서 Kubernetes 클러스터를 운영하면서 개발팀의 비효율성을 해결하려고 찾아보다가 알게 된 프로젝트였다. Kubernetes를 도입한 지 오래되지 않아서 익숙하지도 않았고 보통 로컬 개발 환경은 docker-compose로 구성해서 사용하기도 하지만 개발 환경이 복잡해 지면서 docker-compose만으로 전체 시스템을 띄우기도 쉽지 않아졌다.

레거시를 개선하면서 레거시 백엔드와 새 백엔드가 다 필요한 경우도 많아졌고 데이터베이스에 캐시서버까지 갈수록 로컬에 띄워야 하는 일은 많아졌고 새로 개발환경을 구성하는 사람들 모두에게 부담이 되었고 로컬 환경이 느려져서 개발하기도 쉽지 않았다. 더군다나 이렇게 해도 Kubernetes 클러스터에 배포한 경우에는 동작하지 않기도 했고 모든 개발자가 자유롭게 Kubernetes 클러스터에 배포해보면서 개발하기에는 Kubernetes에 대한 지식이 너무 많이 필요했다. 특히 프론트엔드 팀은 SPA 앱을 띄우기 위해서 이 모든 환경을 띄워야 했기에 더욱 부담이 컸다.

예전에는 Skaffold에 대해서 들어봤지만 Telepresence2018년 5월부터 CNCF의 Sandbox 프로젝트가 되었으므로 Telepresence에 더 관심이 갔다.(난 Skaffold는 안써봤지만 스터디에서 논의해보니 로컬 개발 목적으로는 Teleprecence가 훨씬 편해 보인다고 한다.) 하지만 당시에는 Telepresence를 봐야지 하면서 다른 업무에 밀려서 결국 테스트해보지 못했고 이번 스터디를 기회 삼아서 살펴봤다.

참고로 다 보고 나니 다른 분이 알려주셔서 Naver에서 Telepresence로 Kubernetes 클러스터에서 실행할 애플리케이션을 로컬 환경에서 개발하기라는 글을 2019년에 올린 걸 알게 되었다. 아마 당시에 봤을 텐데 그때는 내가 Kubernetes를 안 쓰던 때라 읽고는 잊었지 싶다.

Telepresence

Telepresence 로고

Telepresence는 Kubernetes에서 마이크로서비스를 개발할 때(Openshift도 된다지만 Openshift는 몰라서...) 빠른 로컬 개발을 위한 도구다. 설명대로 프로덕션 용도는 아니고 개발 및 디버깅 용도의 도구다.

Kubernetes 클러스터에 A라는 서버를 배포했을 때 기능을 변경하고 다시 확인하려면...

  1. 코드를 수정한다.
  2. Docker 이미지를 빌드한다.
  3. Docker 이미지를 레지스트리에 푸시한다.
  4. Kubernetes에 새 이미지를 적용한다.

보통 2, 3, 4 단계는 CI/CD에 자동화되어 있겠지만 그래도 무척 번거로운 작업이고 특히 Kubernetes에 적용했는데 단순 실수나 설정 오류를 발견해서 다시 처음부터 해야 한다면 피곤하기도 피곤하고 아주 비효율적으로 된다.

Telepresence는 딱 이 과정을 편하게 만들어 준다.

Telepresence 설치

설치 문서에 OS별 설치 방법이 나와 있는데 나는 macOS를 쓰고 있어서 Homebrew로 설치했다.

$ brew cask install osxfuse
$ brew install datawire/blackbird/telepresence

자주 업데이트하거나 아직 쓸지 안 쓸지 모르는 도구는 직접 설치하는 편이라 소스로 설치하는 방법도 살펴봤지만 의존성이 있어서 수동 설치하기가 좀 번거로워 보여서 그냥 brew를 이용했다.

$ telepresence --version
0.108

현재 최신 버전은 0.108이다.

테스트를 위한 환경 준비

내부 동작을 설명할 정도로 자세히 살펴보지 않았고 이에 대해서는 앞에서 언급한 Telepresence로 Kubernetes 클러스터에서 실행할 애플리케이션을 로컬 환경에서 개발하기가 더 도움이 될 것 같다.

간단히 설명하면 Telepresence가 로컬환경과 Kubernetes 클러스터 사이의 프락시를 만들어 주어서 로컬에서 쉽게 Kubernetes 클러스터 안으로 들어가 보거나 로컬이 Kubernetes 클러스터와 연결된 것처럼 사용할 수 있다.

사용해보니 직접 동작하는 걸 보는 게 이해하기가 좋아서 테스트를 할 수 있는 환경을 준비하자. Telepresence 사이트는 Python으로 설명하고 있지만 Node.js가 더 익숙해서 Node.js로 환경을 준비했다.

먼저 Docker 이미지 2개를 Docker Hub에 배포했다.

  • outsideris/express-test:latest
  • outsideris/express-test:hello

태그만 다를 뿐이지만 express를 사용한 웹 애플리케이션으로 동작은 같고 아래의 express-generator를 이용해서 다음과 같이 소스를 생성했다.

$ npx express-generator

다음은 routes/index.js 파일이다.

var express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/', function(req, res, next) {
  res.send('Express\n');
});

module.exports = router;

여기서 6번 라인이 원래는 res.render('index', { title: 'Express' });로 되어 있었는데 HTML은 CLI에서 보기가 더 어려워서 res.send('Express\n');로 수정했다.

  • outsideris/express-test:latest : res.send('Express\n');
  • outsideris/express-test:hello : res.send('Hello World\n');

/로 요청을 보냈을 때 latestExpress를 응답하고 helloHello World를 응답한다. 서버를 구분하기 위해서 응답만 다르게 했을 뿐이다.

이를 배포하기 위해 Kubernetes 설정 파일을 YAML로 만들었다. 이 YAML에는 다음을 배포한다.

  • express-test 이름의 Deployment
  • 위 Deployment를 보는 express-test라는 이름의 Service
  • hello-world 이름의 Deployment
  • 위 Deployment를 보는 hello-world라는 이름의 Service

전체 파일은 아래와 같다.

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: express-test
  name: express-test
spec:
  replicas: 1
  selector:
    matchLabels:
      app: express-test
  template:
    metadata:
      labels:
        app: express-test
    spec:
      containers:
      - image: outsideris/express-test:latest
        name: express-test
        imagePullPolicy: Always
        ports:
        - containerPort: 3000

---

apiVersion: v1
kind: Service
metadata:
  labels:
    app: express-test
  name: express-test
spec:
  ports:
  - port: 3000
    protocol: TCP
    targetPort: 3000
  selector:
    app: express-test

---

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: hello-world
  name: hello-world
spec:
  replicas: 1
  selector:
    matchLabels:
      app: hello-world
  template:
    metadata:
      labels:
        app: hello-world
    spec:
      containers:
      - image: outsideris/express-test:hello
        name: hello-world
        imagePullPolicy: Always
        ports:
        - containerPort: 3000

---

apiVersion: v1
kind: Service
metadata:
  labels:
    app: hello-world
  name: hello-world
spec:
  ports:
  - port: 4000
    protocol: TCP
    targetPort: 3000
  selector:
    app: hello-world

이 파일을 example.yml로 저장하고 kubectl로 적용한다.

$ kubectl -n demo apply -f example.yml
deployment.apps/express-test created
service/express-test created
deployment.apps/hello-world created
service/hello-world created

배포된 상황을 확인해 보면 정상적으로 실행된 것을 볼 수 있다.

$ kubectl -n demo get all
NAME                                READY   STATUS    RESTARTS   AGE
pod/express-test-7dcd799b77-57f98   1/1     Running   0          48s
pod/hello-world-6b58c7db7b-dzn9g    1/1     Running   0          48s

NAME                   TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
service/express-test   ClusterIP   172.20.147.49    <none>        3000/TCP   48s
service/hello-world    ClusterIP   172.20.151.224   <none>        4000/TCP   48s

NAME                           READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/express-test   1/1     1            1           48s
deployment.apps/hello-world    1/1     1            1           48s

NAME                                      DESIRED   CURRENT   READY   AGE
replicaset.apps/express-test-7dcd799b77   1         1         1       48s
replicaset.apps/hello-world-6b58c7db7b    1         1         1       48s

간단한 테스트이므로 다른 리소스는 생성하지 않았다. 서비스가 ClusterIP로 설정되어 있기 때문에 클러스터 밖에서는 접근할 수가 없다.

Telepresence로 Kubernetes 클러스터 접근하기

클러스터에 프락시를 열어서 curl로 요청을 보내보자.

telepresence --docker-run --rm -it pstauffer/curl curl http://express-test:3000 명령어를 이용하는데 --docker-run 옵션을 주어서 Docker를 실행하는데 pstauffer/curl 이미지를 이용해서 curl http://express-test:3000을 실행한다. 서비스를 express-test로 실행했으므로 express-test:3000으로 요청을 보내는데 당연히 express-test는 Kubernetes 클러스터 안에서만 인식하는 URL이고 로컬에서는 알 수 없는 URL이다.

$ telepresence --docker-run --rm -it pstauffer/curl curl http://express-test:3000
T: Using a Pod instead of a Deployment for the Telepresence proxy. If you experience problems,
T:  please file an issue!
T: Set the environment variable TELEPRESENCE_USE_DEPLOYMENT to any non-empty value to force
T: the old behavior, e.g.,
T:     env TELEPRESENCE_USE_DEPLOYMENT=1 telepresence --run curl hello

T: Volumes are rooted at $TELEPRESENCE_ROOT. See https://telepresence.io/howto/volumes.html
T: for details.
T: Starting network proxy to cluster using new Pod telepresence-1610560813-567848-4981

T: No traffic is being forwarded from the remote Deployment to your local machine. You can use
T:  the --expose option to specify which ports you want to forward.

T: Setup complete. Launching your container.
Express
T: Your process has exited.
T: Exit cleanup in progress
T: Cleaning up Pod

여기서 앞에 T:가 붙은 것은 Telepresence의 로그이고 마지막에 보면 Express가 출력된 것을 볼 수 있다.

마찬가지로 http://hello-world:4000으로 요청을 보내면 아래처럼 Hello World 응답이 제대로 온 것을 볼 수 있다.

$ telepresence --docker-run --rm -it pstauffer/curl curl http://hello-world:4000
T: Using a Pod instead of a Deployment for the Telepresence proxy. If you experience problems,
T:  please file an issue!
T: Set the environment variable TELEPRESENCE_USE_DEPLOYMENT to any non-empty value to force
T: the old behavior, e.g.,
T:     env TELEPRESENCE_USE_DEPLOYMENT=1 telepresence --run curl hello

T: Volumes are rooted at $TELEPRESENCE_ROOT. See https://telepresence.io/howto/volumes.html
T: for details.
T: Starting network proxy to cluster using new Pod telepresence-1610561034-018354-5178

T: No traffic is being forwarded from the remote Deployment to your local machine. You can use
T:  the --expose option to specify which ports you want to forward.

T: Setup complete. Launching your container.
Hello World
T: Your process has exited.
T: Exit cleanup in progress
T: Cleaning up Pod

위의 명령어를 실행하는 중에 kubectl로 조회해 보면 아래처럼 telepresence-1610561203-7136698-5367이라는 pod이 실행된 것을 알 수 있다.

$ kubectl -n demo get all
NAME                                       READY   STATUS    RESTARTS   AGE
pod/express-test-7dcd799b77-8zk57          1/1     Running   0          28m
pod/hello-world-6b58c7db7b-6trkh           1/1     Running   0          28m
pod/telepresence-1610561203-7136698-5367   1/1     Running   0          8s

NAME                   TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
service/express-test   ClusterIP   172.20.18.29   <none>        3000/TCP   28m
service/hello-world    ClusterIP   172.20.115.9   <none>        4000/TCP   28m

NAME                           READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/express-test   1/1     1            1           28m
deployment.apps/hello-world    1/1     1            1           28m

NAME                                      DESIRED   CURRENT   READY   AGE
replicaset.apps/express-test-7dcd799b77   1         1         1       28m
replicaset.apps/hello-world-6b58c7db7b    1         1         1       28m

이처럼 클러스터 내에 Pod를 띄우고(여기서는 pstauffer/curl 컨테이너) 이 Pod를 실행 결과를 로컬에서 보여준 것이기 때문에 Kubernetes 클러스터 내에 접근한 것처럼 다른 서비스에 요청을 보내서 확인해 볼 수 있다.

참고로 telepresence를 터미널 세션에서 처음 실행하면 sudo가 필요하다고 비밀번호를 입력하라고 나오고 macOS 기준으로는 아래처럼 권한 요청이 나와서 이를 허용해 주어야 한다.

The system extension required for mounting FUSE volumes could not be loaded.

Docker가 네트워크 볼륨의 파일에 접급하려고 합니다


Telepresence로 Docker 이미지를 이용한 로컬 개발

위에서는 Kubernetes 클러스터에 접근해서 요청을 보내봤는데 간단한 확인 정도는 가능하겠지만 실제로 개발하려면 이로써는 부족하다.

위에서 express-generator로 생성한 샘플 프로젝트에서 npm install로 의존성을 설치한다.

Node.js에서는 코드를 변경해도 재시작하기 전에는 변경된 코드가 반영되지 않으므로 로컬 개발을 편하게 하려고 npm install nodemon으로 nodemon을 설치한다. Dockerfile에서 CMD npm start로 서버를 실행하므로 이 부분을 수정해야 하는데 현재 package.json에서 start 스크립트 부분은 다음과 같이 되어 있다.

"scripts": {
  "start": "node ./bin/www"
},

nodemon을 이용하도록 다음과 같이 변경한다.

"scripts": {
  "start": "nodemon ./bin/www"
},

수정한 코드를 기반으로 다시 Docker 이미지를 생성한다. 이 이미지는 로컬에서만 사용할 것이므로 demo:latest 태그를 사용했다.

$ docker build -t demo:latest .
Sending build context to Docker daemon  10.57MB
Step 1/6 : FROM node:14
 ---> 995ff80c793e
Step 2/6 : WORKDIR /app
 ---> Using cache
 ---> 38bfa3d28369
Step 3/6 : COPY . .
 ---> 4bdd5105ec40
Step 4/6 : RUN npm install --production
 ---> Running in fb255632cb37
audited 218 packages in 1.349s

11 packages are looking for funding
  run `npm fund` for details

found 4 vulnerabilities (3 low, 1 critical)
  run `npm audit fix` to fix them, or `npm audit` for details
Removing intermediate container fb255632cb37
 ---> 37925d9d888a
Step 5/6 : EXPOSE 3000
 ---> Running in 3c4aa0198577
Removing intermediate container 3c4aa0198577
 ---> 1bfd537619b7
Step 6/6 : CMD npm start
 ---> Running in 9e2799ed744e
Removing intermediate container 9e2799ed744e
 ---> 03d124a6da5f
Successfully built 03d124a6da5f
Successfully tagged demo:latest

참고로 Dockerfile은 다음과 같다.

FROM node:14

WORKDIR /app
COPY . .

RUN npm install --production

EXPOSE 3000

CMD npm start

이제 이 Docker 이미지를 telepresence로 연결한다. 명령어는 telepresence --swap-deployment express-test --docker-run --rm -it -v $(pwd):/app demo:latest를 사용한다.

  • --swap-deployment 옵션을 사용해서 express-test Deployment를 교체한다.
  • 교체할 때는 뒤에 --docker-run으로 실행한 Docker로 바꿔치기한다. 여기서 실행한 이미지는 로컬의 demo:latest이다.
  • 로컬에서 docker를 실행할 때는 -v $(pwd):/app로 현재 디렉터리(express 프로젝트의 루트 디렉터리)를 Docker 이미지 내의 WORKDIR로 볼륨을 연결한다.
$ telepresence --swap-deployment express-test --docker-run --rm -it -v $(pwd):/app demo:latest
T: Using a Pod instead of a Deployment for the Telepresence proxy. If you experience problems,
T:  please file an issue!
T: Set the environment variable TELEPRESENCE_USE_DEPLOYMENT to any non-empty value to force
T: the old behavior, e.g.,
T:     env TELEPRESENCE_USE_DEPLOYMENT=1 telepresence --run curl hello

T: How Telepresence uses sudo: https://www.telepresence.io/reference/install#dependencies
T: Invoking sudo. Please enter your sudo password.
Password:
T: Volumes are rooted at $TELEPRESENCE_ROOT. See https://telepresence.io/howto/volumes.html
T: for details.
T: Starting network proxy to cluster by swapping out Deployment express-test with a proxy Pod
T: Forwarding remote port 3000 to local port 3000.

T: Setup complete. Launching your container.

> example@0.0.0 start /app
> nodemon ./bin/www

[nodemon] 2.0.7
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `node ./bin/www

위를 보면 nodemon으로 서버가 실행된 것을 볼 수 있다.

터미널을 하나 더 실행해서 kubectlpstauffer/curl 이미지를 띄워서 sh을 실행한다. 이건 Telepresence와는 상관없고 Kubernetes에 바로 컨테이너를 띄워서 접속한 것이다. 그리고 curl http://express-test:3000로 요청을 보내면 원래대로 Express가 응답 오는 걸 알 수 있다.

$ kubectl run curler -it --rm --image=pstauffer/curl --restart=Never -- sh
If you don't see a command prompt, try pressing enter.
/ # curl http://express-test:3000
Express

로컬에서 routes/index.js 파일의 res.send('Express\n');res.send('Express modified\n');로 수정한다.

그리고 아까 실행한 curl 이미지에서 다시 요청을 보내보면 로컬에서 변경된 내용이 바로 적용된 것을 알 수 있다.

kubectl run curler -it --rm --image=pstauffer/curl --restart=Never -- sh
If you don't see a command prompt, try pressing enter.
/ # curl http://express-test:3000
Express
/ # curl http://express-test:3000
Express modified

이를 이용하면 로컬에서 내가 원하는 에디터(VS Code나 Web Storm이나)로 수정하면서 변경된 내용을 바로 확인할 수 있다.

Telepresence로 로컬 개발 서버에 바로 연결하기

위에서 Docker 이미지로 로컬 수정사항을 바로 적용할 수 있게 연결했지만, 로컬에 개발하는 것처럼 편하지는 않다. Kubernetes 클러스터 내의 Deployment를 로컬에서 접속할 수 있게 바로 열어보자.

이번에는 telepresence --swap-deployment express-test --expose 3000 --run npm start 명령어를 이용했다.

  • --swap-deploymentexpress-test라는 Deployment를 교체한다.
  • --expose 3000으로 pod의 3000 포트를 로컬의 3000 포트로 포워딩한다.
  • --run npm start로 앞에서 --docker-run 대신 로컬 명령어 npm start를 실행한다.
$ telepresence --swap-deployment express-test --expose 3000 --run npm start
T: Using a Pod instead of a Deployment for the Telepresence proxy. If you experience problems,
T:  please file an issue!
T: Set the environment variable TELEPRESENCE_USE_DEPLOYMENT to any non-empty value to force
T: the old behavior, e.g.,
T:     env TELEPRESENCE_USE_DEPLOYMENT=1 telepresence --run curl hello

T: Starting proxy with method 'vpn-tcp', which has the following limitations: All processes
T: are affected, only one telepresence can run per machine, and you can't use other VPNs. You
T: may need to add cloud hosts and headless services with --also-proxy. For a full list of
T: method limitations see https://telepresence.io/reference/methods.html
T: Volumes are rooted at $TELEPRESENCE_ROOT. See https://telepresence.io/howto/volumes.html
T: for details.
T: Starting network proxy to cluster by swapping out Deployment express-test with a proxy Pod
T: Forwarding remote port 3000 to local port 3000.

T: Connected. Flushing DNS cache.
T: Setup complete. Launching your command.

> example@0.0.0 start /Users/outsider/Dropbox/projects/infrastructure/aws-cb-infrastructure/example
> nodemon ./bin/www

[nodemon] 2.0.7
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `node ./bin/www`

앞에서 수정했으므로 npm start를 하면 nodemon으로 실행된 것을 볼 수 있다.

$ kubectl -n demo get pod
NAME                                                READY   STATUS              RESTARTS   AGE
express-test-7dcd799b77-xrzdd                   1/1     Terminating         0          40s
express-test-f6a14f473fe34ed3bea9db8fe6cedcab   0/1     ContainerCreating   0          2s
hello-world-6b58c7db7b-6trkh                    1/1     Running             0          57m

위에서 Docker 이미지를 이용했을 때와 마찬가지로 telepresence --swap-deployment를 실행했을 때 pod를 조회해보면 기존 express-test Pod이 내려가고(express-test-7dcd799b77-xrzdd) telepresence가 프락시를 열기 위해서 만드는 새 Pod(express-test-f6a14f473fe34ed3bea9db8fe6cedcab)이 뜨는 것을 볼 수 있다.(테스트 해봤을 때 replicas가 여러 대로 지정되어 있으면 --swap-deployment 할 때 replicas가 여러 대여도 모두 내려가서 telepresence가 띄운 새 Pod이 실행된다. 다시 말하면 프로덕션에서 사용하면 큰일 난다는 얘기다)

이제 로컬에서 nodemon으로 서버를 띄웠고 이 서버가 Telepresence로 Kubernetes 클러스터와 연결되었다.

크롬 브라우저에서 localhost:3000에 접속

로컬에서 웹브라우저로 접속해 보면 아까 수정한 Express modified가 잘 나오는 것을 볼 수 있고 당연히 로컬에서 수정하면(nodmon이 서버를 새 시작하고) 변경된 내용이 나온다. 하지만 Telepresence 없이도 npm start 하면 로컬에선 저렇게 나오는 게 맞기 때문에 제대로 Kubernetes 클러스터와 연결된 건지 확인하기가 어렵다.

routes/index.js 파일을 현재 아래처럼 작성되어 있다.

var express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/', function(req, res, next) {
  res.send('Express modified\n');
});

module.exports = router;

이를 아래와 같이 수정한다. 이는 http 모듈을 이용해서 앞에 띄워두었던 hello-worl Pod에 HTTP 요청을 보내고 그 응답을 res.send(Express with ${data} on ${process.env.KUBERNETES_SERVICE_HOST}\n);로 같이 내려준다. 내려주면서 Kubernetes 내에 실행될 때 같이 설정되는 환경 변수인 KUBERNETES_SERVICE_HOST도 같이 내려준다.

var express = require('express');
var router = express.Router();
var http = require('http');

/* GET home page. */
router.get('/', function(req, res, next) {
  http.request({
      hostname: "hello-world",
      port: 4000,
      path: "/"
    },
    response => {
      let data = "";
      response.on("data", d => { data += d });
      response.on("end", () => {
        res.send(`Express with ${data} on ${process.env.KUBERNETES_SERVICE_HOST}\\n`);
      });
    }
  ).end();
});

module.exports = router;

다시 로컬에서 웹브라우저로 접속하면 Express with Hello World on 172.20.0.1\n가 출력된 것을 볼 수 있다. 여기서 Hello World 부분은 hello-world 서버가 응답해 준 것이므로 로컬에 띄운 Node.js 서버가 마치 Kubernetes 클러스터 안에서 실행된 것처럼 클러스터의 다른 리소스에 접근할 수 있는 것을 알 수 있다.

크롬 브라우저에서 localhost:3000에 접속

이렇게 실행한 telepresence 명령어는 Ctrl + C 같은 인터럽트 명령어로 종료하면 자동으로 Pod이 내려가고 원래 Deployment의 Pod들이 새로 뜨게 된다.

그 외 명령어

앞에서는 기존의 배포한 Deployment를 교체하는 방식을 설명했는데 아직 배포하지 않은 애플리케이션이나 테스트 목적으로 로컬에서 바로 Kubernetes 클러스터에 연결해서 바로 개발하는 것도 가능하다.

아래처럼 --new-deployment를 이용해서 기존 Deployment와는 상관없이 새로운 Pod이 배포되면서 로컬에 띄운 서버와 프락시로 연결해서 Kubernetes 클러스터 환경에서 개발할 수 있다.

$ telepresence --new-deployment test-purpose --expose 3000 --run npm start
T: Using a Pod instead of a Deployment for the Telepresence proxy. If you experience problems,
T:  please file an issue!
T: Set the environment variable TELEPRESENCE_USE_DEPLOYMENT to any non-empty value to force
T: the old behavior, e.g.,
T:     env TELEPRESENCE_USE_DEPLOYMENT=1 telepresence --run curl hello

T: Starting proxy with method 'vpn-tcp', which has the following limitations: All processes
T: are affected, only one telepresence can run per machine, and you can't use other VPNs. You
T: may need to add cloud hosts and headless services with --also-proxy. For a full list of
T: method limitations see https://telepresence.io/reference/methods.html
T: Volumes are rooted at $TELEPRESENCE_ROOT. See https://telepresence.io/howto/volumes.html
T: for details.
T: Starting network proxy to cluster using new Pod infra-study
T: Forwarding remote port 3000 to local port 3000.

T: Connected. Flushing DNS cache.
T: Setup complete. Launching your command.

> example@0.0.0 start /Users/outsider/Dropbox/projects/infrastructure/aws-cb-infrastructure/example
> nodemon ./bin/www

[nodemon] 2.0.7
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `node ./bin/www`

그리고 앞에서는 설명을 위해 curl을 실행하려고 curl Docker 이미지를 이용했지만, 로컬에 curl이 설치되어 있으면 아래처럼 바로 로컬 명령어를 실행해서 확인하는 것도 가능하다.

$ telepresence --run curl http://express-test:3000/
T: Using a Pod instead of a Deployment for the Telepresence proxy. If you experience problems,
T:  please file an issue!
T: Set the environment variable TELEPRESENCE_USE_DEPLOYMENT to any non-empty value to force
T: the old behavior, e.g.,
T:     env TELEPRESENCE_USE_DEPLOYMENT=1 telepresence --run curl hello

T: Starting proxy with method 'vpn-tcp', which has the following limitations: All processes
T: are affected, only one telepresence can run per machine, and you can't use other VPNs. You
T: may need to add cloud hosts and headless services with --also-proxy. For a full list of
T: method limitations see https://telepresence.io/reference/methods.html
T: Volumes are rooted at $TELEPRESENCE_ROOT. See https://telepresence.io/howto/volumes.html
T: for details.
T: Starting network proxy to cluster using new Pod telepresence-1610565191-484263-8216

T: No traffic is being forwarded from the remote Deployment to your local machine. You can use
T:  the --expose option to specify which ports you want to forward.

T: Connected. Flushing DNS cache.
T: Setup complete. Launching your command.
Express
T: Your process has exited.
T: Exit cleanup in progress
T: Cleaning up Pod


사용해 본 느낌

아직 업무에서는 사용해 보지 않고 테스트만 해봤지만, 생각보다 너무 쉽게 Kubernetes 클러스터와 연결해서 개발할 수 있어서 상당히 편해 보였다.

그리고 telepresence를 이용하지 않더라도 kubectl이나 HELM을 이용하면 로컬에서 컨테이너를 바로 배포해서 테스트해보는 것도 가능하지만 이 경우 개발자가 kubectl과 HELM의 사용법을 상당히 익혀야 하는 것에 반해서 telepresence는 훨씬 쉽게 사용할 수 있을 것으로 보이고 로컬 서버에 연결할 경우 Docker 이미지 빌드조차도 필요 없다는 것은 생산성을 많이 높여줄 것으로 보인다.

추가로 맥북이 1대뿐이라 정확히 테스트는 못 해봤지만 두 터미널에서 telepresence --swap-deployment ...를 했을 때 기존 Deployment는 내려가지만, telepresence가 띄운 Pod는 둘 다 뜨는 것으로 보아 여러 명이 동시에 사용해도 충돌 없이 사용할 수 있다고 생각된다.

2021/01/14 04:36 2021/01/14 04:36