<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Kubernetes 이야기</title>
    <link>https://kmaster.tistory.com/</link>
    <description>kubernetes 이야기</description>
    <language>ko</language>
    <pubDate>Thu, 7 May 2026 05:22:23 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>kmaster</managingEditor>
    <item>
      <title>BuildKit 빌드</title>
      <link>https://kmaster.tistory.com/193</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;224&quot; data-origin-height=&quot;224&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KbMKJ/dJMcagL17iV/qm12Kf7lg7s6iYOVppdAMk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KbMKJ/dJMcagL17iV/qm12Kf7lg7s6iYOVppdAMk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KbMKJ/dJMcagL17iV/qm12Kf7lg7s6iYOVppdAMk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKbMKJ%2FdJMcagL17iV%2Fqm12Kf7lg7s6iYOVppdAMk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;224&quot; height=&quot;224&quot; data-origin-width=&quot;224&quot; data-origin-height=&quot;224&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;buildkit으로 이미지 빌드 후 K8S에 배포하는 방법에 대해 알아보자. 핵심은 &lt;b&gt;BuildKit 데몬을 클러스터 내에 띄우고&lt;/b&gt;, &lt;b&gt;buildctl 클라이언트로 빌드를 트리거&lt;/b&gt;한 뒤, &lt;b&gt;빌드된 이미지를 private registry에 push&lt;/b&gt;하고, 그 이미지를 참조하는 &lt;b&gt;Pod를 배포&lt;/b&gt;하는 흐름이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. BuildKit 데몬 배포 (rootless, StatefulSet)&lt;/h3&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #14181f;&quot;&gt;&lt;code&gt;apiVersion: v1
kind: ServiceAccount
metadata:
  name: buildkit
  namespace: build-system
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: buildkitd
  namespace: build-system
spec:
  serviceName: buildkitd
  replicas: 2  # 동시 빌드 처리량에 맞춰 조정
  selector:
    matchLabels:
      app: buildkitd
  template:
    metadata:
      labels:
        app: buildkitd
      annotations:
        container.apparmor.security.beta.kubernetes.io/buildkitd: unconfined
        container.seccomp.security.alpha.kubernetes.io/buildkitd: unconfined
    spec:
      serviceAccountName: buildkit
      containers:
        - name: buildkitd
          image: moby/buildkit:v0.13.2-rootless
          args:
            - --addr
            - unix:///run/user/1000/buildkit/buildkitd.sock
            - --addr
            - tcp://0.0.0.0:1234
            - --oci-worker-no-process-sandbox
          readinessProbe:
            exec:
              command: [&quot;buildctl&quot;, &quot;debug&quot;, &quot;workers&quot;]
            initialDelaySeconds: 5
            periodSeconds: 30
          livenessProbe:
            exec:
              command: [&quot;buildctl&quot;, &quot;debug&quot;, &quot;workers&quot;]
            initialDelaySeconds: 5
            periodSeconds: 30
          securityContext:
            seccompProfile:
              type: Unconfined
            runAsUser: 1000
            runAsGroup: 1000
          ports:
            - containerPort: 1234
          volumeMounts:
            - name: buildkitd
              mountPath: /home/user/.local/share/buildkit
  volumeClaimTemplates:
    - metadata:
        name: buildkitd
      spec:
        accessModes: [&quot;ReadWriteOnce&quot;]
        resources:
          requests:
            storage: 30Gi  # 캐시 용량
---
apiVersion: v1
kind: Service
metadata:
  name: buildkitd
  namespace: build-system
spec:
  selector:
    app: buildkitd
  ports:
    - port: 1234
      targetPort: 1234
  clusterIP: None  # headless, StatefulSet pod별 직접 접근&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;rootless를 권장하는 이유&lt;/b&gt;: privileged 컨테이너가 필요 없고 PSA(Pod Security Admission) restricted 네임스페이스에서도 동작 가능. 다만 OverlayFS가 fuse-overlayfs로 fallback되므로 빌드 속도는 약간 저하됨. 성능이 우선이라면 moby/buildkit:v0.13.2 (rootful) + securityContext.privileged: true로 변경.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. Registry 인증용 Secret&lt;/h3&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;bash&quot; style=&quot;color: #14181f;&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;kubectl -n build-system create secret docker-registry regcred \
  --docker-server=harbor.registry.local \
  --docker-username=builder \
  --docker-password='****' \
  --docker-email=kmaster8k@gmail.com&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 빌드 Job (buildctl 클라이언트 + Git context)&lt;/h3&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;bash&quot; style=&quot;color: #14181f;&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;apiVersion: batch/v1
kind: Job
metadata:
  name: build-myapp-001
  namespace: build-system
spec:
  backoffLimit: 0
  template:
    spec:
      restartPolicy: Never
      containers:
        - name: buildctl
          image: moby/buildkit:v0.13.2-rootless
          command: [&quot;sh&quot;, &quot;-c&quot;]
          args:
            - |
              buildctl \
                --addr tcp://buildkitd-0.buildkitd.build-system.svc.cluster.local:1234 \
                build \
                --frontend=dockerfile.v0 \
                --opt context=https://github.com/git/example-dockerfile-python.git#master \
                --opt filename=Dockerfile \
                --output type=image,name=harbor.registry.local/apps/helloworld:v1.0.0,push=true
          env:
            - name: DOCKER_CONFIG
              value: /home/user/.docker
          volumeMounts:
            - name: docker-config
              mountPath: /home/user/.docker
              readOnly: true
      volumes:
        - name: docker-config
          secret:
            secretName: regcred
            items:
              - key: .dockerconfigjson
                path: config.json&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;핵심 포인트&lt;/b&gt;:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;context=https://... &amp;mdash; Git URL을 직접 전달하면 별도 sidecar로 clone할 필요 없음. 로컬 디렉터리를 보내려면 buildctl build --local context=. --local dockerfile=. 패턴 사용 (이 경우 kubectl exec 또는 stdin 스트리밍 필요).&lt;/li&gt;
&lt;li&gt;output=type=image,push=true &amp;mdash; 빌드 직후 바로 registry로 push.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Kubernetes/일반</category>
      <category>buildkit</category>
      <author>kmaster</author>
      <guid isPermaLink="true">https://kmaster.tistory.com/193</guid>
      <comments>https://kmaster.tistory.com/193#entry193comment</comments>
      <pubDate>Wed, 22 Apr 2026 13:20:00 +0900</pubDate>
    </item>
    <item>
      <title>kubernetes에서 nvidia gpu 공유하기</title>
      <link>https://kmaster.tistory.com/192</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;512&quot; data-origin-height=&quot;512&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IM4uo/dJMcaibnYZc/mckCcGWXB8lvNIl0qWhd0K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IM4uo/dJMcaibnYZc/mckCcGWXB8lvNIl0qWhd0K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IM4uo/dJMcaibnYZc/mckCcGWXB8lvNIl0qWhd0K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIM4uo%2FdJMcaibnYZc%2FmckCcGWXB8lvNIl0qWhd0K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;143&quot; height=&quot;143&quot; data-origin-width=&quot;512&quot; data-origin-height=&quot;512&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최근 AI 워크로드가 kubernetes위에 배포되어 운영되는 사례가 증가하고 있다. kubernetes에서 nvidia gpu를 여러 instance 로 사용하기 위해서는 대표적으로 mig, time slicing, multi-process server (mps) 방식이 있다. 이 외에&amp;nbsp; 가상화를 이용한 vGPU ( vGPU 라이선스 필요 ) 기술도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 중 gpu 공유기술의 대표적인 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;mig, time slicing, multi-process server (mps)&lt;span&gt; 를 알아보자. 아래 그림은 time slicing, mps, mig 를 이해하기 쉽게 표현한 그림이다.&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;707&quot; data-origin-height=&quot;369&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xOPpM/dJMcaiJailX/2tEeHHs5jxBJhIKWTr8x3k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xOPpM/dJMcaiJailX/2tEeHHs5jxBJhIKWTr8x3k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xOPpM/dJMcaiJailX/2tEeHHs5jxBJhIKWTr8x3k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxOPpM%2FdJMcaiJailX%2F2tEeHHs5jxBJhIKWTr8x3k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;707&quot; height=&quot;369&quot; data-origin-width=&quot;707&quot; data-origin-height=&quot;369&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.flaticon.com/kr/free-icon/gpu_1089003?related_id=1088744&amp;amp;origin=search&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;출처 : https://www.flaticon.com/kr/free-icon/gpu_1089003?related_id=1088744&amp;amp;origin=search&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 430px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;width: 19.6512%; text-align: center; height: 21px;&quot;&gt;항목&lt;/td&gt;
&lt;td style=&quot;width: 27.3255%; text-align: center; height: 21px;&quot;&gt;MIG&lt;/td&gt;
&lt;td style=&quot;width: 28.0233%; text-align: center; height: 21px;&quot;&gt;&lt;span style=&quot;background-color: #9b9b9b; color: #ffffff; text-align: center;&quot;&gt;MPS&amp;nbsp;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; text-align: center; height: 21px;&quot;&gt;&lt;span style=&quot;background-color: #9b9b9b; color: #ffffff; text-align: center;&quot;&gt;Time-Slicing&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 63px;&quot;&gt;
&lt;td style=&quot;width: 19.6512%; height: 63px;&quot;&gt;지원 GPU&lt;/td&gt;
&lt;td style=&quot;width: 27.3255%; height: 63px;&quot;&gt;A30, A100, H100, B100 등&lt;br /&gt;( MIG 를 지원하는 GPU 모델이 존재함 )&lt;/td&gt;
&lt;td style=&quot;width: 28.0233%; height: 63px;&quot;&gt;Volta 이상 권장&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 63px;&quot;&gt;대부분의 GPU가 지원&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;width: 19.6512%; height: 21px;&quot;&gt;격리 수준&lt;/td&gt;
&lt;td style=&quot;width: 27.3255%; height: 21px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 28.0233%; height: 21px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 21px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;width: 19.6512%; height: 21px;&quot;&gt;&amp;nbsp; &amp;nbsp; 메모리&lt;/td&gt;
&lt;td style=&quot;width: 27.3255%; height: 21px;&quot;&gt;하드웨어 레벨 완전 격리&lt;/td&gt;
&lt;td style=&quot;width: 28.0233%; height: 21px;&quot;&gt;격리 없음&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 21px;&quot;&gt;격리&amp;nbsp;없음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;width: 19.6512%; height: 21px;&quot;&gt;&amp;nbsp; &amp;nbsp; 컴퓨팅&lt;/td&gt;
&lt;td style=&quot;width: 27.3255%; height: 21px;&quot;&gt;SM (Streaming Multiprocessor) 파티셔닝&lt;/td&gt;
&lt;td style=&quot;width: 28.0233%; height: 21px;&quot;&gt;부분 격리 ( SM 비율 지정 )&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 21px;&quot;&gt;격리&amp;nbsp;없음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;width: 19.6512%; height: 21px;&quot;&gt;&amp;nbsp; &amp;nbsp; 장애&lt;/td&gt;
&lt;td style=&quot;width: 27.3255%; height: 21px;&quot;&gt;장애 전파 없음&lt;/td&gt;
&lt;td style=&quot;width: 28.0233%; height: 21px;&quot;&gt;한 프로세스 장애 시 전체 영향&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 21px;&quot;&gt;한 프로세스 장애 시 전체 영향&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 19.6512%; height: 17px;&quot;&gt;리소스 분할&lt;/td&gt;
&lt;td style=&quot;width: 27.3255%; height: 17px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 28.0233%; height: 17px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 17px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 19.6512%; height: 17px;&quot;&gt;&amp;nbsp; &amp;nbsp; 분할 방식&lt;/td&gt;
&lt;td style=&quot;width: 27.3255%; height: 17px;&quot;&gt;GPU를 인스턴스로 분할&lt;br /&gt;(pod 할당 시에는 nvidia.com/mig-1g.6gb: &quot;1&quot; 와 같이 프로파일 이름으로 할당해야 함)&lt;/td&gt;
&lt;td style=&quot;width: 28.0233%; height: 17px;&quot;&gt;SM&amp;nbsp;비율(%)&amp;nbsp;기반&amp;nbsp;분할&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 17px;&quot;&gt;시간&amp;nbsp;기반&amp;nbsp;교대&amp;nbsp;사용 &lt;br /&gt;(라운드로빈&amp;nbsp;스케줄링)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 19.6512%; height: 17px;&quot;&gt;&amp;nbsp; &amp;nbsp; 분한 단위&lt;/td&gt;
&lt;td style=&quot;width: 27.3255%; height: 17px;&quot;&gt;GPU&amp;nbsp;Instance&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 28.0233%; height: 17px;&quot;&gt;프로세스 단위 SM 비율&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 17px;&quot;&gt;컨테이너/프로세스 단위&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 19.6512%; height: 17px;&quot;&gt;&amp;nbsp; &amp;nbsp; 최대 공유 수&lt;/td&gt;
&lt;td style=&quot;width: 27.3255%; height: 17px;&quot;&gt;최대 7개 인스턴스&lt;/td&gt;
&lt;td style=&quot;width: 28.0233%; height: 17px;&quot;&gt;최대&amp;nbsp;48개&amp;nbsp;클라이언트&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 17px;&quot;&gt;제한 없음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;width: 19.6512%; height: 21px;&quot;&gt;&amp;nbsp; &amp;nbsp; 메모리 할당&lt;/td&gt;
&lt;td style=&quot;width: 27.3255%; height: 21px;&quot;&gt;고정 할당&lt;/td&gt;
&lt;td style=&quot;width: 28.0233%; height: 21px;&quot;&gt;동적 할당 (전체 메모리 공유)&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 21px;&quot;&gt;동적 할당 (전체 메모리 공유)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;width: 19.6512%; height: 21px;&quot;&gt;성능&lt;/td&gt;
&lt;td style=&quot;width: 27.3255%; height: 21px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 28.0233%; height: 21px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 21px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;width: 19.6512%; height: 21px;&quot;&gt;&amp;nbsp; &amp;nbsp; 오버헤드&lt;/td&gt;
&lt;td style=&quot;width: 27.3255%; height: 21px;&quot;&gt;거의 없음&lt;/td&gt;
&lt;td style=&quot;width: 28.0233%; height: 21px;&quot;&gt;낮음&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 21px;&quot;&gt;높음 ( 컨텍스트 스위칭 )&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;width: 19.6512%; height: 21px;&quot;&gt;&amp;nbsp; &amp;nbsp; 동시 실행&lt;/td&gt;
&lt;td style=&quot;width: 27.3255%; height: 21px;&quot;&gt;각 인스턴스 독립 동시 실행&lt;/td&gt;
&lt;td style=&quot;width: 28.0233%; height: 21px;&quot;&gt;커널 레벨 동시 실행&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 21px;&quot;&gt;순차 실행&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;width: 19.6512%; height: 21px;&quot;&gt;&amp;nbsp; &amp;nbsp; 지연 시간&lt;/td&gt;
&lt;td style=&quot;width: 27.3255%; height: 21px;&quot;&gt;낮음&lt;/td&gt;
&lt;td style=&quot;width: 28.0233%; height: 21px;&quot;&gt;낮음&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 21px;&quot;&gt;높음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 19.6512%; height: 17px;&quot;&gt;K8S 사용&lt;/td&gt;
&lt;td style=&quot;width: 27.3255%; height: 17px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 28.0233%; height: 17px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 17px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 19.6512%; height: 17px;&quot;&gt;&amp;nbsp; &amp;nbsp; 필수 Plugin&lt;/td&gt;
&lt;td style=&quot;width: 27.3255%; height: 17px;&quot;&gt;nvidia-device-plugin&lt;br /&gt;(strategy:&amp;nbsp;mig)&lt;/td&gt;
&lt;td style=&quot;width: 28.0233%; height: 17px;&quot;&gt;nvidia-device-plugin&lt;br /&gt;(strategy:&amp;nbsp;mps,&amp;nbsp;K8s&amp;nbsp;1.28+)&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 17px;&quot;&gt;nvidia-device-plugin&lt;br /&gt;(strategy:&amp;nbsp;time-slicing)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 19.6512%; height: 17px;&quot;&gt;&amp;nbsp; &amp;nbsp; 리소스 요청&lt;/td&gt;
&lt;td style=&quot;width: 27.3255%; height: 17px;&quot;&gt;nvidia.com/mig-1g.6gb: 1&lt;br /&gt;( kubectl describe node 정보의 Labels을 참고하면 된다.)&lt;/td&gt;
&lt;td style=&quot;width: 28.0233%; height: 17px;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #030712; text-align: start;&quot;&gt;nvidia.com/gpu: 1&lt;br /&gt;또는&lt;br /&gt;nvidia.com/gpu.shared: 1&lt;br /&gt;(설정에 따라 다름)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 17px;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #030712; text-align: start;&quot;&gt;nvidia.com/gpu: 1&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 19.6512%; height: 17px;&quot;&gt;&amp;nbsp; &amp;nbsp; 설정 복잡도&lt;/td&gt;
&lt;td style=&quot;width: 27.3255%; height: 17px;&quot;&gt;높음 (프로파일 계획 필요, 재구성 시 GPU 리셋 필요)&lt;/td&gt;
&lt;td style=&quot;width: 28.0233%; height: 17px;&quot;&gt;중간&amp;nbsp;(MPS&amp;nbsp;데몬&amp;nbsp;관리&amp;nbsp;필요)&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 17px;&quot;&gt;낮음&amp;nbsp;(ConfigMap&amp;nbsp;설정만으로&amp;nbsp;가능)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 19.6512%;&quot;&gt;&amp;nbsp; &amp;nbsp; 모니터링&lt;br /&gt;&amp;nbsp; &amp;nbsp; (prometheus exporter 기준)&lt;/td&gt;
&lt;td style=&quot;width: 27.3255%;&quot;&gt;전체 지원&lt;/td&gt;
&lt;td style=&quot;width: 28.0233%;&quot;&gt;일부지원&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 25%;&quot;&gt;N/A&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영에서는 가급적 MIG를 추천하지만, 개발환경에서는 MPS나 Time-Slicing 방식이 적합할 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고문서&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/NVIDIA/k8s-device-plugin&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/NVIDIA/k8s-device-plugin&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://docs.nvidia.com/deploy/mps/when-to-use-mps.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://docs.nvidia.com/deploy/mps/when-to-use-mps.html&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://docs.nvidia.com/deploy/mps/architecture.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://docs.nvidia.com/deploy/mps/architecture.html&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://docs.nvidia.com/datacenter/cloud-native/gpu-operator/latest/gpu-sharing.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://docs.nvidia.com/datacenter/cloud-native/gpu-operator/latest/gpu-sharing.html&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://www.researchgate.net/figure/Multi-Stream-MPS-and-MIG-Illustration-ture-Figure-2-a-As-a-software-based_fig1_359309310&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.researchgate.net/figure/Multi-Stream-MPS-and-MIG-Illustration-ture-Figure-2-a-As-a-software-based_fig1_359309310&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://developer.nvidia.com/blog/improving-gpu-utilization-in-kubernetes/#:~:text=You%20can%20take%20the%20oversubscription%20strategy%20described,to%20execute%20in%20parallel%20on%20the%20GPU.&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://developer.nvidia.com/blog/improving-gpu-utilization-in-kubernetes/#:~:text=You%20can%20take%20the%20oversubscription%20strategy%20described,to%20execute%20in%20parallel%20on%20the%20GPU.&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Kubernetes/MLOps</category>
      <category>gpu operator</category>
      <category>kubernetes &amp;amp; nvidia gpu</category>
      <category>mig</category>
      <category>MPS</category>
      <category>Nvidia GPU</category>
      <category>Time Slicing</category>
      <author>kmaster</author>
      <guid isPermaLink="true">https://kmaster.tistory.com/192</guid>
      <comments>https://kmaster.tistory.com/192#entry192comment</comments>
      <pubDate>Mon, 2 Mar 2026 19:08:47 +0900</pubDate>
    </item>
    <item>
      <title>nvidia k8s device driver 및 dcgm 설치</title>
      <link>https://kmaster.tistory.com/187</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;637&quot; data-origin-height=&quot;104&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bmniR7/btsHmq4Kgvv/UpAXWzP4karP5OB76nB0ik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bmniR7/btsHmq4Kgvv/UpAXWzP4karP5OB76nB0ik/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bmniR7/btsHmq4Kgvv/UpAXWzP4karP5OB76nB0ik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbmniR7%2FbtsHmq4Kgvv%2FUpAXWzP4karP5OB76nB0ik%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;637&quot; height=&quot;104&quot; data-origin-width=&quot;637&quot; data-origin-height=&quot;104&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Kubernetes에서 nvidia gpu 를 사용하고, prometheus로 gpu 모니터링을 위한 절차를 알아보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;설치 전 nvidia driver는 노드에 설치되어 있어야 한다.&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;설치&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;b&gt;1. container-toolkit 설치&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;
&lt;pre id=&quot;codecell4&quot; class=&quot;awk&quot; style=&quot;color: #1a1a1a; text-align: left;&quot;&gt;&lt;code&gt;curl -s -L https://nvidia.github.io/libnvidia-container/stable/rpm/nvidia-container-toolkit.repo | \
  sudo tee /etc/yum.repos.d/nvidia-container-toolkit.repo&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1715424871828&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo yum-config-manager --enable nvidia-container-toolkit-experimental&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;codecell6&quot; class=&quot;sql&quot; style=&quot;color: #1a1a1a; text-align: left;&quot;&gt;&lt;code&gt;sudo yum install -y nvidia-container-toolkit&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치 후 설정&lt;/p&gt;
&lt;pre id=&quot;code_1715424969940&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo nvidia-ctk runtime configure --runtime=containerd
sudo systemctl restart containerd&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;b&gt;2, kubernetes에 GPU 활성화&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1715425002405&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ kubectl create -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/v0.15.0/deployments/static/nvidia-device-plugin.yml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;테스트&lt;/h3&gt;
&lt;pre id=&quot;code_1715425221090&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ cat &amp;lt;&amp;lt;EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: gpu-pod
spec:
  restartPolicy: Never
  containers:
    - name: cuda-container
      image: nvcr.io/nvidia/k8s/cuda-sample:vectoradd-cuda10.2
      resources:
        limits:
          nvidia.com/gpu: 1 # requesting 1 GPU
  tolerations:
  - key: nvidia.com/gpu
    operator: Exists
    effect: NoSchedule
EOF&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1715425096543&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ k logs -f -n default gpu-pod
[Vector addition of 50000 elements]
Copy input data from the host memory to the CUDA device
CUDA kernel launch with 196 blocks of 256 threads
Copy output data from the CUDA device to the host memory
Test PASSED
Done&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;모니터링&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a style=&quot;background-color: #ffffff; color: #1a1a1a; text-align: left;&quot; href=&quot;https://developer.nvidia.com/dcgm&quot; data-wpel-link=&quot;internal&quot;&gt;NVIDIA DCGM은&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;대규모 Linux 기반 클러스터 환경에서 NVIDIA GPU를 관리하고 모니터링하기 위한 도구 세트이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;624&quot; data-origin-height=&quot;399&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b7gZSS/btsHma1KjKS/yM9ttbWJXeAxrhm5lXaCNK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b7gZSS/btsHma1KjKS/yM9ttbWJXeAxrhm5lXaCNK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b7gZSS/btsHma1KjKS/yM9ttbWJXeAxrhm5lXaCNK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb7gZSS%2FbtsHma1KjKS%2FyM9ttbWJXeAxrhm5lXaCNK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;546&quot; height=&quot;349&quot; data-origin-width=&quot;624&quot; data-origin-height=&quot;399&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1715425732092&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ helm repo add gpu-helm-charts https://nvidia.github.io/dcgm-exporter/helm-charts
$ helm repo update&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1715426668046&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ helm install \
    --generate-name \
    gpu-helm-charts/dcgm-exporter -n kube-system&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 설치하면 dcgm을 위한 servicemonitor가 생성된다.&lt;/p&gt;
&lt;pre id=&quot;code_1715436016277&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  annotations:
    meta.helm.sh/release-name: dcgm-exporter-1715426946
    meta.helm.sh/release-namespace: kube-system
  generation: 1
  labels:
    #app.kubernetes.io/component: dcgm-exporter
    #app.kubernetes.io/instance: dcgm-exporter-1715426946
    #app.kubernetes.io/managed-by: Helm
    #app.kubernetes.io/name: dcgm-exporter
    #app.kubernetes.io/version: 3.4.1
    #helm.sh/chart: dcgm-exporter-3.4.1
    release: prometheus
  name: dcgm-exporter-1715426946
  namespace: kube-system
spec:
  endpoints:
  - interval: 15s
    path: /metrics
    port: metrics
    relabelings: []
  namespaceSelector:
    matchNames:
    - kube-system
  selector:
    matchLabels:
      app.kubernetes.io/component: dcgm-exporter
      app.kubernetes.io/instance: dcgm-exporter-1715426946
      app.kubernetes.io/name: dcgm-exporter&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 label -&amp;gt; release: prometheus 를 설정한다. ( 필자는 &lt;a href=&quot;https://github.com/prometheus-community/helm-charts/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/prometheus-community/helm-charts/&lt;/a&gt; 차트를 이용하여 설치한 helm install 이름을 사용하였다. )&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1663&quot; data-origin-height=&quot;544&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bJ8gId/btsHmWoavy5/W6Itla4uwUocIIiSQ5wtDK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bJ8gId/btsHmWoavy5/W6Itla4uwUocIIiSQ5wtDK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bJ8gId/btsHmWoavy5/W6Itla4uwUocIIiSQ5wtDK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbJ8gId%2FbtsHmWoavy5%2FW6Itla4uwUocIIiSQ5wtDK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1663&quot; height=&quot;544&quot; data-origin-width=&quot;1663&quot; data-origin-height=&quot;544&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;b&gt;참고&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/NVIDIA/k8s-device-plugin&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/NVIDIA/k8s-device-plugin&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/NVIDIA/dcgm-exporter&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/NVIDIA/dcgm-exporter&lt;/a&gt;&lt;/p&gt;</description>
      <category>Kubernetes/일반</category>
      <category>dcgm</category>
      <category>dcgm exporter</category>
      <category>kubernetes&amp;amp;nvidia</category>
      <category>Nvidia</category>
      <category>nvidia drvier</category>
      <author>kmaster</author>
      <guid isPermaLink="true">https://kmaster.tistory.com/187</guid>
      <comments>https://kmaster.tistory.com/187#entry187comment</comments>
      <pubDate>Sat, 11 May 2024 23:02:40 +0900</pubDate>
    </item>
    <item>
      <title>OpenSearch 및 Fluent Bit로 Kubernetes Event 및 Container 로그 저장하기</title>
      <link>https://kmaster.tistory.com/186</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;730&quot; data-origin-height=&quot;121&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQrCXK/btsHbU5lChc/gLYq6mtQCf6HmH1tKFWTHk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQrCXK/btsHbU5lChc/gLYq6mtQCf6HmH1tKFWTHk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQrCXK/btsHbU5lChc/gLYq6mtQCf6HmH1tKFWTHk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQrCXK%2FbtsHbU5lChc%2FgLYq6mtQCf6HmH1tKFWTHk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;730&quot; height=&quot;121&quot; data-origin-width=&quot;730&quot; data-origin-height=&quot;121&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;OpenSearch&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a style=&quot;color: #0972d3; text-align: start;&quot; href=&quot;https://opensearch.org/&quot;&gt;OpenSearch&lt;/a&gt;는 &lt;span style=&quot;background-color: #ffffff; color: #343741; text-align: start;&quot;&gt;Amazon에서 만든 OpenSearch 프로젝트는 이전 버전의 Elasticsearch와 Kibana를 기반으로 하는 포크(fork)된 검색 프로젝트&lt;/span&gt; 로 Apache 2.0 라이선스 하에 제공되는 분산형 커뮤니티 기반 100% 오픈 소스 검색 및 분석 제품군군이다. 실시간 애플리케이션 모니터링, 로그 분석 및 웹 사이트 검색과 같이 다양한 사용 사례에 사용된다. OpenSearch는 데이터 탐색을 쉽게 해주는 통합 시각화 도구 OpenSearch 대시보드와 함께 대량 데이터 볼륨에 빠르게 액세스하고 응답하며 뛰어난 확장성을 지닌 시스템을 제공한다. OpenSearch는 Apache Lucene 검색 라이브러리로 구동되며 k-nearest neighbors(KNN) 검색, SQL, Anomaly Detection, Machine Learning Commons, Trace Analytics, 전체 텍스트 검색 등 다수의 검색 및 분석 기능을 지원한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;u&gt;설치&lt;/u&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1714878038911&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ helm repo add opensearch https://opensearch-project.github.io/helm-charts/
$ helm repo update
$ helm pull opensearch/opensearch --untar&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;values를 알맞게 수정한다.&lt;u&gt;&lt;br /&gt;&lt;br /&gt;&lt;/u&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1714878111864&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;extraEnvs:
#  - name: MY_ENVIRONMENT_VAR
#    value: the_value_goes_here
# Chart version 2.18.0 and App Version OpenSearch 2.12.0 onwards a custom strong password needs to be provided in order to setup demo admin user.
# Cluster will not spin-up without this unless demo config install is disabled.
  - name: OPENSEARCH_INITIAL_ADMIN_PASSWORD
    value: test#2321&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테스트&lt;/p&gt;
&lt;pre id=&quot;code_1714878127287&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ curl -u &quot;admin:test#2321&quot; -k https://ip:9200/_cat/indices?v
health status index                           uuid                   pri rep docs.count docs.deleted store.size pri.store.size
green  open   .ql-datasources                 XPSbtmETT5-kkUhEwwg5Lw   1   0          0            0       208b           208b
green  open   .kibana_92668751_admin_1        ic6oGRFtSkyf48Uh5vaMeQ   1   0          6            0     30.5kb         30.5kb
green  open   .opendistro-reports-definitions 8pWzhdq9R7akVZHCUff5VQ   1   0          0            0       208b           208b
green  open   .opendistro_security            55f_ZSZtSTaU0cMM-_q0fA   1   0         10            0     79.1kb         79.1kb
green  open   .kibana_1                       RbiAx1inRLKhk4ut-PQ_4w   1   0          7            1     40.7kb         40.7kb
green  open   .opendistro-reports-instances   FZ0MdanlRIONmCGju_TJOA   1   0          1            0      6.6kb          6.6kb
green  open   .tasks                          jl4FOIBfSHG4iFBfy2gjrg   1   0          3            0     20.7kb         20.7kb
green  open   .plugins-ml-config              1rrI3UiSSxGDcxWWC3KumA   1   0          1            0      3.9kb          3.9kb
green  open   .opensearch-observability       kCXF5ml5R_amxBMuQtM66A   1   0          1            0      6.3kb          6.3kb&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;u&gt;&lt;br /&gt;&lt;/u&gt;&lt;b&gt;Fluent Bit&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a style=&quot;background-color: color(srgb 1 1 1); color: #000000; text-align: start;&quot; href=&quot;http://fluentbit.io/&quot;&gt;Fluent Bit&lt;/a&gt; 는 Linux, macOS, Windows 및 BSD 제품군 운영 체제용 로그, 지표 및 추적을 위한 빠르고 가벼운 &lt;b&gt;원격 측정 에이전트&lt;/b&gt;이다. 복잡성 없이 다양한 소스에서 원격 측정 데이터를 수집하고 처리할 수 있도록 성능에 중점을 두고 만들어졌다.&lt;span style=&quot;background-color: color(srgb 1 1 1); color: color(srgb 0.120353 0.120353 0.120353); text-align: start;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주요특징&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: color(srgb 1 1 1); color: color(srgb 0.120353 0.120353 0.120353); text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고성능: 낮은 리소스 소비로 높은 처리량&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터 분석&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.fluentbit.io/manual/pipeline/parsers/json&quot;&gt;JSON&lt;/a&gt; , &lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.fluentbit.io/manual/pipeline/parsers/regular-expression&quot;&gt;Regex&lt;/a&gt; , &lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.fluentbit.io/manual/pipeline/parsers/ltsv&quot;&gt;LTSV&lt;/a&gt; 및 &lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.fluentbit.io/manual/pipeline/parsers/logfmt&quot;&gt;Logfmt&lt;/a&gt; 파서를 사용하여 구조화되지 않은 메시지를 변환&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;측정항목 지원: Prometheus 및 OpenTelemetry 호환&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;신뢰성 및 데이터 무결성&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;네트워킹&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;보안: 내장형 TLS/SSL 지원&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비동기 I/O&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;플러그형 아키텍처 및 &lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.fluentbit.io/manual/development/library_api&quot;&gt;확장성&lt;/a&gt; : 입력, 필터 및 출력
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존 플러그인을 사용하여 거의 모든 소스를 거의 모든 대상에 연결&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.fluentbit.io/manual/administration/monitoring&quot;&gt;모니터링&lt;/a&gt; : HTTP를 통해 JSON 및 &lt;a style=&quot;color: #000000;&quot; href=&quot;https://prometheus.io/&quot;&gt;Prometheus&lt;/a&gt; 형식 으로 내부 측정항목을 노출&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.fluentbit.io/manual/stream-processing/introduction&quot;&gt;스트림 처리&lt;/a&gt; : 간단한 SQL 쿼리를 사용하여 데이터 선택 및 변환 수행&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쿼리 결과를 사용하여 새로운 데이터 스트림 생성&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;집계 창&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터 분석 및 예측: 시계열 예측&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;휴대용: Linux, macOS, Windows 및 BSD 시스템에서 실행&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1&quot; data-origin-height=&quot;1&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MrgMd/btsHb4s7krV/p2AkkAZKXhqTcmKWmzJij0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MrgMd/btsHb4s7krV/p2AkkAZKXhqTcmKWmzJij0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MrgMd/btsHb4s7krV/p2AkkAZKXhqTcmKWmzJij0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMrgMd%2FbtsHb4s7krV%2Fp2AkkAZKXhqTcmKWmzJij0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1&quot; height=&quot;1&quot; data-origin-width=&quot;1&quot; data-origin-height=&quot;1&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;b&gt;설치&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1714878776227&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ helm repo add fluent https://fluent.github.io/helm-charts
$ helm repo update
$ helm pull fluent/fluent-bit --untar
$ kubectl create ns fluent-bit&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;values 수정&lt;/p&gt;
&lt;pre id=&quot;code_1714878795109&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[values]
rbac:
  create: true
  nodeAccess: true
  eventsAccess: true


  inputs: |
    [INPUT]
        Name tail
        Path /var/log/containers/*.log
        multiline.parser docker, cri
        Tag kube.*
        Mem_Buf_Limit 5MB
        Skip_Long_Lines On

    [INPUT]
        Name systemd
        Tag host.*
        Systemd_Filter _SYSTEMD_UNIT=kubelet.service
        Read_From_Tail On

    [INPUT]
        name            kubernetes_events
        tag             k8s_events
        kube_url        https://kubernetes.default.svc


  outputs: |
    [OUTPUT]
        Name es
        Match kube.*
        Host opensearch-cluster-master.opensearch.svc
        Port            9200
        tls             On
        tls.verify      Off
        http_user       admin
        http_passwd     test#2321
        Logstash_Format On
        Retry_Limit False
        Suppress_Type_Name On

    [OUTPUT]
        Name es
        Match host.*
        Host opensearch-cluster-master.opensearch.svc
        Port            9200
        tls             On
        tls.verify      Off
        http_user       admin
        http_passwd     test#2321
        Logstash_Format On
        Logstash_Prefix node
        Retry_Limit False
        Suppress_Type_Name On

    [OUTPUT]
        name            opensearch
        match           k8s_events
        Host            opensearch-cluster-master.opensearch.svc
        Port            9200
        tls             On
        tls.verify      Off
        http_user       admin
        http_passwd     test#2321
        logstash_format true
        logstash_prefix kubernetes-events
        Suppress_Type_Name On&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치 실행&lt;/p&gt;
&lt;pre id=&quot;code_1714878842856&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;helm upgrade --install fluent-bit . -f values.yaml -n fluent-bit&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모니터링을 위해 OpenSearch Dashboard를 설치해 보자.&lt;/p&gt;
&lt;pre id=&quot;code_1714878901253&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;* OpenSearch Dashboard

$ helm pull opensearch/opensearch-dashboards --untar
$ helm upgrade --install opensearch-dashboards . -f values.yaml -n opensearch&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 OpenSearch Dashboard에 접속하여 생성된 Event 로깅을 살펴보자.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1506&quot; data-origin-height=&quot;797&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dlzRGb/btsHaX2TI5b/rJ8feQEcTJ6LtgBl4dPBM1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dlzRGb/btsHaX2TI5b/rJ8feQEcTJ6LtgBl4dPBM1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dlzRGb/btsHaX2TI5b/rJ8feQEcTJ6LtgBl4dPBM1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdlzRGb%2FbtsHaX2TI5b%2FrJ8feQEcTJ6LtgBl4dPBM1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;726&quot; height=&quot;384&quot; data-origin-width=&quot;1506&quot; data-origin-height=&quot;797&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Kubernetes/일반</category>
      <category>fluentbit</category>
      <category>kubernetes event logging</category>
      <category>kuberntes logging</category>
      <category>opensearch</category>
      <category>opensearch dashboard</category>
      <author>kmaster</author>
      <guid isPermaLink="true">https://kmaster.tistory.com/186</guid>
      <comments>https://kmaster.tistory.com/186#entry186comment</comments>
      <pubDate>Mon, 6 May 2024 22:54:24 +0900</pubDate>
    </item>
    <item>
      <title>온라인 서빙과 배치 서빙</title>
      <link>https://kmaster.tistory.com/185</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dbXd3J/btsHeZkdBRP/XZaBLuqJAOZxX7kgfD76A0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dbXd3J/btsHeZkdBRP/XZaBLuqJAOZxX7kgfD76A0/img.webp&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dbXd3J/btsHeZkdBRP/XZaBLuqJAOZxX7kgfD76A0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdbXd3J%2FbtsHeZkdBRP%2FXZaBLuqJAOZxX7kgfD76A0%2Fimg.webp&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;284&quot; height=&quot;284&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;기계 학습 모델을 제공한다는 것은 사용자에게 실시간 예측을 제공하거나 오프라인 사용을 위한 일괄 예측을 제공하기 위해 예측 또는 추론에 사용할 수 있도록 하는 것을 의미한다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;모델 서빙과 관련된 다양한 오픈소스가 있으니, 간단한 모델의 경우 Framework보다 Flask나 Fastapi로 구현하는 경우가 실제 많다. MLFlow에 저장된 모델을 사용하여 온라인 서빙 또는 배치 서빙 하는 방법을 알아보자.&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;온라인 서빙 (Online Serving)&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;온라인 서빙은 실시간 또는 거의 실시간 응답을 제공해야 하는 경우에 적합하다. API를 통해 요청이 들어오면 바로 결과를 반환하게 된다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;구현 방법&lt;/b&gt;:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal; background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;FastAPI 또는 Flask 사용&lt;/b&gt;: REST API 서버를 구축하는 데 FastAPI 또는 Flask 같은 웹 프레임워크를 사용&lt;/li&gt;
&lt;li&gt;&lt;b&gt;모델 로드 및 인퍼런스&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;MLflow로 모델을 로드&lt;/li&gt;
&lt;li&gt;로드된 모델을 사용하여 예측을 수행&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;모니터링&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;예측 성능, 서버 부하, 에러 등을 모니터링하여 서빙 상태를 추적&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;예시 코드&lt;/b&gt;:&lt;/p&gt;
&lt;pre id=&quot;code_1715002997364&quot; class=&quot;reasonml&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;from fastapi import FastAPI, HTTPException
import mlflow.pyfunc
import pandas as pd
from pydantic import BaseModel

# FastAPI 앱 생성
app = FastAPI()

# MLflow 모델 로드 (예: &quot;runs:/&amp;lt;your_run_id&amp;gt;/model&quot;)
model_uri = &quot;runs:/&amp;lt;your_run_id&amp;gt;/model&quot;
model = mlflow.pyfunc.load_model(model_uri)

class ModelInput(BaseModel):
    feature1: float
    feature2: float
    feature3: float
    feature4: float

@app.post(&quot;/predict&quot;)
def predict(input_data: ModelInput):
    try:
        data_df = pd.DataFrame([input_data.dict()])
        prediction = model.predict(data_df)
        return {&quot;prediction&quot;: prediction.tolist()}
    except Exception as e:
        raise HTTPException(status_code=400, detail=str(e))&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;배치 서빙 (Batch Serving)&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;배치 서빙은 대량의 데이터를 한 번에 처리하는 경우에 적합하다. 배치 작업은 일반적으로 예약된 일정에 따라 또는 이벤트에 의해 트리거된다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;구현 방법&lt;/b&gt;:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal; background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;데이터 소스 및 대상 정의&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;데이터를 어디에서 가져오고, 결과를 어디에 저장할지 결정한다. 예를 들어, S3 버킷이나 데이터베이스.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;MLflow 모델 로드 및 배치 인퍼런스&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;MLflow로 모델을 로드&lt;/li&gt;
&lt;li&gt;데이터를 불러와 배치로 예측을 수행&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;배치 작업 스케줄링&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;작업 예약을 위해 스케줄링 도구를 사용&lt;/li&gt;
&lt;li&gt;Airflow나 Argo Workflow등을 사용하면 데이터 파이프라인 자동화 및 워크플로 관리에 도움이 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;예시 코드&lt;/b&gt;:&lt;/p&gt;
&lt;pre id=&quot;code_1715003002355&quot; class=&quot;makefile&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;import mlflow.pyfunc
import pandas as pd

# MLflow 모델 로드
model_uri = &quot;runs:/&amp;lt;your_run_id&amp;gt;/model&quot;
model = mlflow.pyfunc.load_model(model_uri)

# 데이터 로드 (예: CSV 파일로부터)
data = pd.read_csv(&quot;input_data.csv&quot;)

# 모델로 배치 예측 수행
predictions = model.predict(data)

# 결과 저장 (예: CSV 파일로 저장)
output_data = pd.DataFrame(predictions, columns=[&quot;predictions&quot;])
output_data.to_csv(&quot;output_predictions.csv&quot;, index=False)&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;통합 및 최적화 고려 사항&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal; background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;인프라 관리&lt;/b&gt;: Kubernetes나 Docker 등을 사용해 온라인 및 배치 서빙을 확장성 있게 관리&lt;/li&gt;
&lt;li&gt;&lt;b&gt;로깅 및 모니터링&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;예측 결과 및 성능 지표를 기록하고 분석&lt;/li&gt;
&lt;li&gt;Prometheus, Grafana 등의 모니터링 시스템을 사용해 서버 상태를 추적&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;보안&lt;/b&gt;: API 요청과 데이터 저장 시 암호화 및 인증 메커니즘을 적용&lt;/li&gt;
&lt;li&gt;&lt;b&gt;자동화&lt;/b&gt;: CI/CD 파이프라인을 구축해 모델 업데이트 시 자동으로 재배포&lt;/li&gt;
&lt;/ol&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이러한 방법을 통해 온라인 서빙과 배치 서빙을 모두 커버하는 모델 서빙 솔루션을 구축할 수 있다.&lt;/p&gt;</description>
      <category>Kubernetes/MLOps</category>
      <category>batch serving</category>
      <category>Model Serving</category>
      <category>online serving</category>
      <category>모델서빙</category>
      <author>kmaster</author>
      <guid isPermaLink="true">https://kmaster.tistory.com/185</guid>
      <comments>https://kmaster.tistory.com/185#entry185comment</comments>
      <pubDate>Mon, 6 May 2024 22:53:20 +0900</pubDate>
    </item>
    <item>
      <title>kr8s - Kubernetes용 Python 클라이언트 라이브러리</title>
      <link>https://kmaster.tistory.com/181</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;894&quot; data-origin-height=&quot;449&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/q5ejj/btsCP4dKxfT/4RjO2m0dhdl85qMLg3Yvpk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/q5ejj/btsCP4dKxfT/4RjO2m0dhdl85qMLg3Yvpk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/q5ejj/btsCP4dKxfT/4RjO2m0dhdl85qMLg3Yvpk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fq5ejj%2FbtsCP4dKxfT%2F4RjO2m0dhdl85qMLg3Yvpk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;627&quot; height=&quot;315&quot; data-origin-width=&quot;894&quot; data-origin-height=&quot;449&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Kubernetes Python 클라이언트 라이브러리는 보통 다음을 참고하여 개발한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/kubernetes-client&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/kubernetes-client&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1704029565633&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;profile&quot; data-og-title=&quot;Kubernetes Clients&quot; data-og-description=&quot;This organization hosts Kubernetes API client libraries. - Kubernetes Clients&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/kubernetes-client&quot; data-og-url=&quot;https://github.com/kubernetes-client&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/kMjY2/hyUXOo1pWm/kL788FhJSevCBjZ1Do9mDk/img.png?width=200&amp;amp;height=200&amp;amp;face=0_0_200_200&quot;&gt;&lt;a href=&quot;https://github.com/kubernetes-client&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/kubernetes-client&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/kMjY2/hyUXOo1pWm/kL788FhJSevCBjZ1Do9mDk/img.png?width=200&amp;amp;height=200&amp;amp;face=0_0_200_200');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Kubernetes Clients&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;This organization hosts Kubernetes API client libraries. - Kubernetes Clients&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;kubernetes-client 는 asynio를 지원하지 않기 때문에 이런 경우에는&amp;nbsp; kubernetes-asyncio를 사용하기도 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/tomplus/kubernetes_asyncio&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/tomplus/kubernetes_asyncio&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1704029614081&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - tomplus/kubernetes_asyncio: Python asynchronous client library for Kubernetes http://kubernetes.io/&quot; data-og-description=&quot;Python asynchronous client library for Kubernetes http://kubernetes.io/ - GitHub - tomplus/kubernetes_asyncio: Python asynchronous client library for Kubernetes http://kubernetes.io/&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/tomplus/kubernetes_asyncio&quot; data-og-url=&quot;https://github.com/tomplus/kubernetes_asyncio&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bdlM99/hyUXQf4YQN/x4wvoNGo6bXCfaNgOtxcL1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/tomplus/kubernetes_asyncio&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/tomplus/kubernetes_asyncio&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bdlM99/hyUXQf4YQN/x4wvoNGo6bXCfaNgOtxcL1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - tomplus/kubernetes_asyncio: Python asynchronous client library for Kubernetes http://kubernetes.io/&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Python asynchronous client library for Kubernetes http://kubernetes.io/ - GitHub - tomplus/kubernetes_asyncio: Python asynchronous client library for Kubernetes http://kubernetes.io/&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러 오픈소스들 중 kubernetes python client로 &lt;a href=&quot;https://docs.kr8s.org/en/stable/index.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;kr8s&lt;/a&gt;를 살펴보자. kr8s는 매&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;우 명확하고 읽기 쉽게 개발을 진행할 수 있는 장점이 있다. 간단히 pod list를 조회하는 예제를 살펴보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;kubernetes-client&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1704029765523&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from kubernetes import client, config

selector = {'component': 'kube-scheduler'}
selector_str = &quot;,&quot;.join([f&quot;{key}={value}&quot; for key, value in selector.items()])

config.load_kube_config()

v1 = client.CoreV1Api()
for pods in v1.list_pod_for_all_namespaces(label_selector=selector_str, ).items:
    print(pod.metadata.namespace, pod.metadata.name)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;kr8s&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1704029798609&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import kr8s

selector = {'component': 'kube-scheduler'}

for pod in kr8s.get(&quot;pods&quot;, namespace=kr8s.ALL, label_selector=selector):
    print(pod.namespace, pod.name)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 눈에 봐도 kr8s가 간결하다는 것을 알 수 있다. 또하는 asyncio도 kubernetes_asyncio 와 비교하면 간결하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;kubernetes_asyncio&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt; &lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1704029894511&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from kubernetes_asyncio import client, config
from kubernetes_asyncio.client.api_client import ApiClient

await config.load_kube_config()

async with ApiClient() as api:
    v1 = client.CoreV1Api(api)
    nodes = await v1.list_node()
    for node in nodes.items:
        print(node.metadata.name)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;kr8s&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1704029911094&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import kr8s.asyncio

for node in await kr8s.asyncio.get(&quot;nodes&quot;):
    print(node.name)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한, 몇 가지 유용한 기능들을 제공한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1) pod gen 기능&lt;/p&gt;
&lt;pre id=&quot;code_1704030282174&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from kr8s.objects import Pod
pod = Pod.gen(name=&quot;my-pod&quot;, image=&quot;my-image&quot;)
pod.create()&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2) owner reference 설정&lt;/p&gt;
&lt;pre id=&quot;code_1704030349323&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from kr8s.objects import Deployment, Pod
deployment = Deployment.get(&quot;my-deployment&quot;)
pod = Pod.get(&quot;my-pod&quot;)
deployment.adopt(pod)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;kr8s 홈페이지로 접속하면 object들에 대한 상세 function 들을 조회할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1503&quot; data-origin-height=&quot;767&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oWRFQ/btsCTUVv7jI/uFkE63oiCMKkMYStwKyAzK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oWRFQ/btsCTUVv7jI/uFkE63oiCMKkMYStwKyAzK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oWRFQ/btsCTUVv7jI/uFkE63oiCMKkMYStwKyAzK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoWRFQ%2FbtsCTUVv7jI%2FuFkE63oiCMKkMYStwKyAzK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1503&quot; height=&quot;767&quot; data-origin-width=&quot;1503&quot; data-origin-height=&quot;767&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1486&quot; data-origin-height=&quot;921&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KJcZT/btsCSzRIAXh/tfCADrD13iT6JXWdfiiGv1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KJcZT/btsCSzRIAXh/tfCADrD13iT6JXWdfiiGv1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KJcZT/btsCSzRIAXh/tfCADrD13iT6JXWdfiiGv1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKJcZT%2FbtsCSzRIAXh%2FtfCADrD13iT6JXWdfiiGv1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1486&quot; height=&quot;921&quot; data-origin-width=&quot;1486&quot; data-origin-height=&quot;921&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Kubernetes/일반</category>
      <category>k8s python client api</category>
      <category>kr8s</category>
      <category>kubernetes python api</category>
      <category>kubernetes python client</category>
      <category>kubernetes python client api</category>
      <author>kmaster</author>
      <guid isPermaLink="true">https://kmaster.tistory.com/181</guid>
      <comments>https://kmaster.tistory.com/181#entry181comment</comments>
      <pubDate>Sun, 31 Dec 2023 22:54:51 +0900</pubDate>
    </item>
    <item>
      <title>Ollama and Chainlit으로 Langchain과 RAG 구현하기</title>
      <link>https://kmaster.tistory.com/180</link>
      <description>&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;213&quot; data-origin-height=&quot;68&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/w76Wp/btsCP5XOW97/zSROo9IBA5s0KOrCFg5lRk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/w76Wp/btsCP5XOW97/zSROo9IBA5s0KOrCFg5lRk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/w76Wp/btsCP5XOW97/zSROo9IBA5s0KOrCFg5lRk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fw76Wp%2FbtsCP5XOW97%2FzSROo9IBA5s0KOrCFg5lRk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;276&quot; height=&quot;88&quot; data-origin-width=&quot;213&quot; data-origin-height=&quot;68&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;&amp;nbsp;&lt;br&gt;최근&amp;nbsp;유행하고&amp;nbsp;있는&amp;nbsp;벡터&amp;nbsp;저장소와&amp;nbsp;같은&amp;nbsp;외부&amp;nbsp;데이터&amp;nbsp;아카이브를&amp;nbsp;사용하여&amp;nbsp;LLM의&amp;nbsp;응답&amp;nbsp;품질을&amp;nbsp;향상시킬&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;기술인&amp;nbsp;LangChain&amp;nbsp;및&amp;nbsp;RAG를&amp;nbsp;사용하는 방법을&amp;nbsp;알아보자.&lt;br&gt;&amp;nbsp;&lt;br&gt;우선 LangChain 에 대해 알아보자.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;u&gt;LangChain&lt;/u&gt;&lt;/b&gt;&lt;/h3&gt;&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;&amp;nbsp;&lt;br&gt;&lt;b&gt;LangChain은&lt;/b&gt;&amp;nbsp;언어 모델을 기반으로 하는 애플리케이션을 개발하기 위한 프레임워크이다.&amp;nbsp;&lt;span style=&quot;color: #1C1E21;&quot;&gt;이는 다음과 같은 애플리케이션을 가능하게 한다.&lt;/span&gt;&lt;/p&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;&lt;b&gt;상황 인식&lt;/b&gt;&amp;nbsp;: 언어 모델을 상황 소스 (즉시 지침, 몇 가지 예시, 응답을 기반으로 하는 콘텐츠 등)에 연결&lt;/li&gt;&lt;li&gt;&lt;b&gt;이유&lt;/b&gt;&amp;nbsp;: 언어 모델을 사용하여 추론 (제공된 맥락에 따라 답변하는 방법, 취해야 할 조치 등에 대해)&lt;/li&gt;&lt;/ul&gt;&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;&amp;nbsp;&lt;br&gt;&lt;b&gt;구성요소&lt;/b&gt;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;902&quot; data-origin-height=&quot;920&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bx5eHl/btsBQpqd0hJ/Z3ezGeTYiOPjkNyQTGcfKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bx5eHl/btsBQpqd0hJ/Z3ezGeTYiOPjkNyQTGcfKk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bx5eHl/btsBQpqd0hJ/Z3ezGeTYiOPjkNyQTGcfKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbx5eHl%2FbtsBQpqd0hJ%2FZ3ezGeTYiOPjkNyQTGcfKk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;615&quot; height=&quot;627&quot; data-origin-width=&quot;902&quot; data-origin-height=&quot;920&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;u&gt;RAG (&amp;nbsp;&lt;span style=&quot;color: #222222;&quot;&gt;Retrieval-Augmented Generation )&lt;/span&gt;&lt;/u&gt;&lt;/b&gt;&lt;/h3&gt;&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #222222;&quot;&gt;RAG는&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #222222;&quot;&gt;LLM에게 미리 질문과 관련된 참고자료를 알려준다. 이렇게 하면 보다 정확하게 대답을 생성할 수 있다.&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #222222;&quot;&gt;ChatPDF 같은 서비스가 대표적인 예이다.&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;b&gt;RAG를 사용하면 추론 시 외부 데이터 저장소를&lt;/b&gt;&amp;nbsp;사용하여&amp;nbsp;보다 풍부한 프롬프트를 생성함으로써 모델의 응답 품질을 향상시킬 수 있다.&lt;br&gt;&amp;nbsp;&lt;br&gt;RAG에는 다음의 요소가 연관되어 있다.&lt;/p&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;Vector Database&lt;/li&gt;&lt;li&gt;PDF나 HTML 등 데이터&lt;/li&gt;&lt;/ul&gt;&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;u&gt;Ollama란&lt;/u&gt;&lt;/b&gt;&lt;/h3&gt;&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #242424;&quot;&gt;Ollama는 로컬 사용을 위해 오픈 소스 모델을 얻을 수 있도록 지원한다.&amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #242424;&quot;&gt;Ollama는 도커 이미지로 액세스할 수 있으므로 개인화된 모델을 도커 컨테이너로 배포할 수 있다.&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;b&gt;&lt;span style=&quot;color: #242424;&quot;&gt;설치&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;curl https://ollama.ai/install.sh | sh&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;&amp;nbsp;&lt;br&gt;&lt;b&gt;&lt;span style=&quot;color: #242424;&quot;&gt;원하는 모델 실행&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;[root@master ~]# # ollama run mistral

pulling manifest
pulling 8934d96d3f08...&amp;nbsp;&amp;nbsp; 3% ▕███&lt;/code&gt;&lt;/pre&gt;&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;u&gt;&lt;span style=&quot;color: #242424;&quot;&gt;Chainlit&lt;/span&gt; &lt;/u&gt;&lt;/b&gt;&lt;/h3&gt;&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #242424;&quot;&gt;Chainlit은 자체 비즈니스 로직과 데이터를 사용하여 Chat GPT와 같은 애플리케이션을 매우 빠르게 구축할 수 있게 해주는 오픈 소스 Python 패키지이다.&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;u&gt;예제&lt;/u&gt;&lt;/b&gt;&lt;/h3&gt;&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;예제는 구조는 다음과 같다.&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;721&quot; data-origin-height=&quot;383&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7JC9C/btsCQ2GAJiw/ExGzr8cOdcC7eKY8oWO0kk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7JC9C/btsCQ2GAJiw/ExGzr8cOdcC7eKY8oWO0kk/img.png&quot; data-alt=&quot;https://medium.aiplanet.com/implementing-rag-using-langchain-ollama-and-chainlit-on-windows-using-wsl-92d14472f15d&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7JC9C/btsCQ2GAJiw/ExGzr8cOdcC7eKY8oWO0kk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7JC9C%2FbtsCQ2GAJiw%2FExGzr8cOdcC7eKY8oWO0kk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;721&quot; height=&quot;383&quot; data-origin-width=&quot;721&quot; data-origin-height=&quot;383&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://medium.aiplanet.com/implementing-rag-using-langchain-ollama-and-chainlit-on-windows-using-wsl-92d14472f15d&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;&amp;nbsp;&lt;br&gt;예제를 만들기전에 우선 jupyterlab을 kubernetes에서 실행 후 아래의 패키지를 설치한다.&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
&amp;nbsp;&amp;nbsp;name: jupyterlab-pvc
spec:
&amp;nbsp;&amp;nbsp;accessModes:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- ReadWriteOnce
&amp;nbsp;&amp;nbsp;resources:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;requests:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;storage: 1Gi
&amp;nbsp;&amp;nbsp;storageClassName: openebs-hostpath
---
apiVersion: apps/v1
kind: Deployment
metadata:
&amp;nbsp;&amp;nbsp;name: jupyterlab
&amp;nbsp;&amp;nbsp;labels:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;name: jupyterlab
spec:
&amp;nbsp;&amp;nbsp;replicas: 1
&amp;nbsp;&amp;nbsp;selector:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;matchLabels:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;name: jupyterlab
&amp;nbsp;&amp;nbsp;template:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;metadata:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;labels:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;name: jupyterlab
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;spec:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;securityContext:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;runAsUser: 0
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fsGroup: 0
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;containers:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- name: jupyterlab
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;image: jupyter/datascience-notebook:latest
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;imagePullPolicy: IfNotPresent
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ports:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- containerPort: 8888
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;command:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- /bin/bash
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- -c
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- |
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;start.sh jupyter lab --LabApp.token='password' --LabApp.ip='0.0.0.0' --LabApp.allow_root=True
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;volumeMounts:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- name: jupyterlab-data
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;mountPath: /home/jovyan
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;resources:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;requests:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;memory: 500Mi
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cpu: 250m
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;restartPolicy: Always
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;volumes:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- name: jupyterlab-data
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;persistentVolumeClaim:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;claimName: jupyterlab-pvc
---
apiVersion: v1
kind: Service
metadata:
&amp;nbsp;&amp;nbsp;name: jupyterlab
&amp;nbsp;&amp;nbsp;labels:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;name: jupyterlab
spec:
&amp;nbsp;&amp;nbsp;type: NodePort
&amp;nbsp;&amp;nbsp;ports:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- port: 80
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;targetPort: 8888
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;nodePort: 31300
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;protocol: TCP
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;name: http
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- port: 9000
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;targetPort: 9000
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;nodePort: 31301
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;protocol: TCP
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;name: http
&amp;nbsp;&amp;nbsp;selector:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;name: jupyterlab&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;&amp;nbsp;&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;pip install chromadb
pip install langchain
pip install BeautifulSoup4
pip install gpt4all
pip install langchainhub
pip install pypdf
pip install chainlit&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;&amp;nbsp;&lt;br&gt;이제 chromadb에 검색에 참조하기 위한 PDF 문서에 대한 전처리를 수행한다. &lt;span style=&quot;color: #242424;&quot;&gt;pdf파일은 &quot;&lt;/span&gt;&lt;a href=&quot;https://www.tutorialspoint.com/apache_spark/apache_spark_tutorial.pdf&quot; target=&quot;_self&quot;&gt;&lt;span&gt;https://www.tutorialspoint.com/apache_spark/apache_spark_tutorial.pdf&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot;color: #242424;&quot;&gt;&quot; 으로 하였다.&lt;/span&gt;&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.document_loaders import PyPDFLoader, DirectoryLoader
from langchain.document_loaders.pdf import PyPDFDirectoryLoader
from langchain.document_loaders import UnstructuredHTMLLoader, BSHTMLLoader
from langchain.vectorstores import Chroma
from langchain.embeddings import GPT4AllEmbeddings
from langchain.embeddings import OllamaEmbeddings&amp;nbsp;&amp;nbsp;

import os

DATA_PATH=&quot;data/&quot;
DB_PATH = &quot;vectorstores/db/&quot;

def create_vector_db():
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;loader = PyPDFDirectoryLoader(DATA_PATH)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;documents = loader.load()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&quot;Processed {len(documents)} pdf files&quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=50)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;texts=text_splitter.split_documents(documents)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;vectorstore = Chroma.from_documents(documents=texts, embedding=GPT4AllEmbeddings(),persist_directory=DB_PATH)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;vectorstore.persist()

if __name__==&quot;__main__&quot;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;create_vector_db()&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #242424;&quot;&gt;&lt;span style=&quot;background-color: #FFFFFF;&quot;&gt;실행 하면 다음과 같이 수행되고, vectorstores폴더에 vector데이터가 저장된다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1191&quot; data-origin-height=&quot;755&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kLsmJ/btsCLojGX6h/qQ3sDXzMHEf0lZSS67ik4k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kLsmJ/btsCLojGX6h/qQ3sDXzMHEf0lZSS67ik4k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kLsmJ/btsCLojGX6h/qQ3sDXzMHEf0lZSS67ik4k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkLsmJ%2FbtsCLojGX6h%2FqQ3sDXzMHEf0lZSS67ik4k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1191&quot; height=&quot;755&quot; data-origin-width=&quot;1191&quot; data-origin-height=&quot;755&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;&amp;nbsp;&lt;br&gt;이제 chainlit을 사용하여 챗봇을 만들어보자.&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;#import required dependencies
from langchain import hub
from langchain.embeddings import GPT4AllEmbeddings
from langchain.vectorstores import Chroma
from langchain.llms import Ollama
from langchain.callbacks.manager import CallbackManager
from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler
import chainlit as cl
from langchain.chains import RetrievalQA,RetrievalQAWithSourcesChain
# Set up RetrievelQA model
QA_CHAIN_PROMPT = hub.pull(&quot;rlm/rag-prompt-mistral&quot;)

#load the LLM
def load_llm():
 llm = Ollama(
 model=&quot;mistral&quot;,
 base_url = &quot;http://10.10.0.5:11434&quot;,
 verbose=True,
 callback_manager=CallbackManager([StreamingStdOutCallbackHandler()]),
 )
 return llm


def retrieval_qa_chain(llm,vectorstore):
 qa_chain = RetrievalQA.from_chain_type(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;llm,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;retriever=vectorstore.as_retriever(),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;chain_type_kwargs={&quot;prompt&quot;: QA_CHAIN_PROMPT},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return_source_documents=True,
)
 return qa_chain


def qa_bot(): 
 llm=load_llm() 
 DB_PATH = &quot;vectorstores/db/&quot;
 vectorstore = Chroma(persist_directory=DB_PATH, embedding_function=GPT4AllEmbeddings())

 qa = retrieval_qa_chain(llm,vectorstore)
 return qa 

@cl.on_chat_start
async def start():
 chain=qa_bot()
 msg=cl.Message(content=&quot;Firing up the research info bot...&quot;)
 await msg.send()
 msg.content= &quot;Hi, welcome to research info bot. What is your query?&quot;
 await msg.update()
 cl.user_session.set(&quot;chain&quot;,chain)

@cl.on_message
async def main(message):
 chain=cl.user_session.get(&quot;chain&quot;)
 cb = cl.AsyncLangchainCallbackHandler(
 stream_final_answer=True,
 answer_prefix_tokens=[&quot;FINAL&quot;, &quot;ANSWER&quot;]
 )
 cb.answer_reached=True
 # res=await chain.acall(message, callbacks=[cb])
 res=await chain.acall(message.content, callbacks=[cb])
 print(f&quot;response: {res}&quot;)
 answer=res[&quot;result&quot;]
 answer=answer.replace(&quot;.&quot;,&quot;.\n&quot;)
 sources=res[&quot;source_documents&quot;]

 if sources:
&amp;nbsp;&amp;nbsp;answer+=f&quot;\nSources: &quot;+str(str(sources))
 else:
&amp;nbsp;&amp;nbsp;answer+=f&quot;\nNo Sources found&quot;

 await cl.Message(content=answer).send()&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;&amp;nbsp;&lt;br&gt;여기서 llm을 load시 Ollama를 사용하는데 별다른 설정이 없으면 &quot;127.0.0.1:11434&quot; 로 요청한다. 필자는 Kubernetes환경에 jupyter에 코드를 실행하고, Ollama는 외부 서버에 있어 host정보를 추가하였다.&lt;br&gt;&amp;nbsp;&lt;br&gt;그리고, ollama 서버도 다음과 같이 host를 지정하여 기동해야 한다.&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;[root@master ~]# export OLLAMA_HOST=0.0.0.0:11434
[root@master ~]# ollama serve&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;&amp;nbsp;&lt;br&gt;이제 chainlit 프로그램을 실행해 보자.&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;chainlit run RAG.py --port 9000 --host 0.0.0.0
2023-12-30 14:02:12 - Your app is available at http://localhost:9000
bert_load_from_file: gguf version&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 2
bert_load_from_file: gguf alignment&amp;nbsp;&amp;nbsp; = 32
bert_load_from_file: gguf data offset = 695552
bert_load_from_file: model name&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = BERT
bert_load_from_file: model architecture&amp;nbsp;&amp;nbsp; = bert
bert_load_from_file: model file type&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;= 1
bert_load_from_file: bert tokenizer vocab = 30522
2023-12-30 14:02:17 - Anonymized telemetry enabled. See&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; https://docs.trychroma.com/telemetry for more information.&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;&amp;nbsp;&lt;br&gt;실행결과는 다음과 같다. &lt;span style=&quot;color: #242424;&quot;&gt;spark shell에 대해 질문한 결과이다.&lt;/span&gt;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1297&quot; data-origin-height=&quot;714&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FSeT4/btsCTAWZJkM/4NL4R4ukQTDLWqqi6iu63K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FSeT4/btsCTAWZJkM/4NL4R4ukQTDLWqqi6iu63K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FSeT4/btsCTAWZJkM/4NL4R4ukQTDLWqqi6iu63K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFSeT4%2FbtsCTAWZJkM%2F4NL4R4ukQTDLWqqi6iu63K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1297&quot; height=&quot;714&quot; data-origin-width=&quot;1297&quot; data-origin-height=&quot;714&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;&amp;nbsp;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1323&quot; data-origin-height=&quot;656&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bqRVVZ/btsCTuvRbS5/EOCsKZaKv8FBXCIU09zbnk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bqRVVZ/btsCTuvRbS5/EOCsKZaKv8FBXCIU09zbnk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bqRVVZ/btsCTuvRbS5/EOCsKZaKv8FBXCIU09zbnk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbqRVVZ%2FbtsCTuvRbS5%2FEOCsKZaKv8FBXCIU09zbnk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1323&quot; height=&quot;656&quot; data-origin-width=&quot;1323&quot; data-origin-height=&quot;656&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;&amp;nbsp;&lt;br&gt;chainlit 로그는 다음과 같다.&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1187&quot; data-origin-height=&quot;742&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/l27CZ/btsCN72Q4hW/dg3ouPFeHKsnYEZUdKfoR0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/l27CZ/btsCN72Q4hW/dg3ouPFeHKsnYEZUdKfoR0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/l27CZ/btsCN72Q4hW/dg3ouPFeHKsnYEZUdKfoR0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fl27CZ%2FbtsCN72Q4hW%2Fdg3ouPFeHKsnYEZUdKfoR0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1187&quot; height=&quot;742&quot; data-origin-width=&quot;1187&quot; data-origin-height=&quot;742&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: left;&quot;&gt;&amp;nbsp;&lt;br&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;b&gt;&lt;u&gt;&lt;span style=&quot;color: #242424;&quot;&gt;참고&lt;/span&gt;&lt;/u&gt;&lt;/b&gt;&lt;br&gt;&lt;u&gt;&lt;a href=&quot;https://python.langchain.com/&quot; target=&quot;_self&quot;&gt;&lt;span&gt;https://python.langchain.com/&lt;/span&gt;&lt;/a&gt;&lt;/u&gt;&lt;br&gt;&lt;a href=&quot;https://medium.aiplanet.com/implementing-rag-using-langchain-ollama-and-chainlit-on-windows-using-wsl-92d14472f15d&quot; target=&quot;_blank&quot;&gt;&lt;span&gt;https://medium.aiplanet.com/implementing-rag-using-langchain-ollama-and-chainlit-on-windows-using-wsl-92d14472f15d&lt;/span&gt;&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;https://github.com/jmorganca/ollama/blob/main/examples/langchain-python-rag-document/main.py&quot; target=&quot;_blank&quot;&gt;&lt;span&gt;https://github.com/jmorganca/ollama/blob/main/examples/langchain-python-rag-document/main.py&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;</description>
      <category>Kubernetes/MLOps</category>
      <category>Chainlit</category>
      <category>chromaDB</category>
      <category>LangChain</category>
      <category>Ollama</category>
      <category>랭체인</category>
      <author>kmaster</author>
      <guid isPermaLink="true">https://kmaster.tistory.com/180</guid>
      <comments>https://kmaster.tistory.com/180#entry180comment</comments>
      <pubDate>Sat, 30 Dec 2023 23:26:26 +0900</pubDate>
    </item>
    <item>
      <title>Nexus에 Pypi 저장소 구축</title>
      <link>https://kmaster.tistory.com/179</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;335&quot; data-origin-height=&quot;151&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sfrRL/btsCQpgLiMl/8jw83afMnjChDUZQioaCC0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sfrRL/btsCQpgLiMl/8jw83afMnjChDUZQioaCC0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sfrRL/btsCQpgLiMl/8jw83afMnjChDUZQioaCC0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsfrRL%2FbtsCQpgLiMl%2F8jw83afMnjChDUZQioaCC0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;335&quot; height=&quot;151&quot; data-origin-width=&quot;335&quot; data-origin-height=&quot;151&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PyPi 는 Python의 온라인 저장소이며 pip install 을 실행할 때 라이브러리가 다운로드되는 곳이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Nexus 에 Pypi 저장소를 구축하는 방법을 알아보좌. 우선 Nexus 에 Repository -&amp;gt; Create repository 를 선택한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1562&quot; data-origin-height=&quot;695&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cxBkTc/btsCMnD93MY/kRpUMPygZM8ktLKKV6dzBK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cxBkTc/btsCMnD93MY/kRpUMPygZM8ktLKKV6dzBK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cxBkTc/btsCMnD93MY/kRpUMPygZM8ktLKKV6dzBK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcxBkTc%2FbtsCMnD93MY%2FkRpUMPygZM8ktLKKV6dzBK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;790&quot; height=&quot;352&quot; data-origin-width=&quot;1562&quot; data-origin-height=&quot;695&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3가지 모드가 있다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;Proxy&lt;/b&gt;&lt;br /&gt;Nexus를 PyPI 프록시로 설정하여 PyPI 서버로부터 패키지를 캐싱한다. 이 방법은 네트워크 대역폭을 절약하고 빠른 속도로 패키지를 제공할 수 있다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Group&lt;/b&gt;&lt;br /&gt;여러 저장소를 그룹으로 묶어서 하나의 저장소처럼 사용하는 방법이다. 그룹 저장소를 통해 여러 소스로부터 패키지를 가져올 수 있다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Hosted&lt;/b&gt;&lt;br /&gt;Nexus에서 직접 PyPI 저장소를 호스팅하는 방법이다. 이 방법은 독립적인 저장소를 만들어 직접 관리하고 사용할 수 있다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;폐쇄망 환경에서 주로 구축하는 Hosted 모드로 생성해 보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선, Pypi를 통해 공유되는 파일 저장 공간을 설정해야 한다. Blob Store 메뉴로 이동해 보자.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1411&quot; data-origin-height=&quot;726&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IwLax/btsCMzYM0eB/akEYFkSxKhz0F4r3VMEREk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IwLax/btsCMzYM0eB/akEYFkSxKhz0F4r3VMEREk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IwLax/btsCMzYM0eB/akEYFkSxKhz0F4r3VMEREk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIwLax%2FbtsCMzYM0eB%2FakEYFkSxKhz0F4r3VMEREk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;677&quot; height=&quot;348&quot; data-origin-width=&quot;1411&quot; data-origin-height=&quot;726&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 Pypi 저장소를 생성해보자.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1213&quot; data-origin-height=&quot;574&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wjQAX/btsCKQfE4xO/6Hk9PeqbaVPS3zePxkMCZ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wjQAX/btsCKQfE4xO/6Hk9PeqbaVPS3zePxkMCZ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wjQAX/btsCKQfE4xO/6Hk9PeqbaVPS3zePxkMCZ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwjQAX%2FbtsCKQfE4xO%2F6Hk9PeqbaVPS3zePxkMCZ0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;698&quot; height=&quot;330&quot; data-origin-width=&quot;1213&quot; data-origin-height=&quot;574&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 저장소에 파일을 등록해 보자. 먼저 whl 파일을 다운로드 받아보자.&lt;/p&gt;
&lt;pre id=&quot;code_1703773245520&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# mkdir download
# cd download
# pip download requests
# ls -al
total 592
drwxr-xr-x   2 root root   4096 Dec 28 23:19 .
drwxrwxr-x 173 root root  53248 Dec 28 23:19 ..
-rw-r--r--   1 root root 162530 Dec 28 23:19 certifi-2023.11.17-py3-none-any.whl
-rw-r--r--   1 root root 140273 Dec 28 23:19 charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
-rw-r--r--   1 root root  61567 Dec 28 23:19 idna-3.6-py3-none-any.whl
-rw-r--r--   1 root root  62574 Dec 28 23:19 requests-2.31.0-py3-none-any.whl
-rw-r--r--   1 root root 104579 Dec 28 23:19 urllib3-2.1.0-py3-none-any.whl&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;b&gt;Upload ( Installing )&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같이 whl 파일을 업로드 할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1050&quot; data-origin-height=&quot;331&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UQinc/btsCG37BeR3/gSdNvdHvWXSJgk9S9JIMp0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UQinc/btsCG37BeR3/gSdNvdHvWXSJgk9S9JIMp0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UQinc/btsCG37BeR3/gSdNvdHvWXSJgk9S9JIMp0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUQinc%2FbtsCG37BeR3%2FgSdNvdHvWXSJgk9S9JIMp0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;641&quot; height=&quot;202&quot; data-origin-width=&quot;1050&quot; data-origin-height=&quot;331&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;901&quot; data-origin-height=&quot;311&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b5Nt3k/btsCOFRLR9M/hKpQpWyMKGAx7C7bNYBSKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b5Nt3k/btsCOFRLR9M/hKpQpWyMKGAx7C7bNYBSKk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b5Nt3k/btsCOFRLR9M/hKpQpWyMKGAx7C7bNYBSKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb5Nt3k%2FbtsCOFRLR9M%2FhKpQpWyMKGAx7C7bNYBSKk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;640&quot; height=&quot;221&quot; data-origin-width=&quot;901&quot; data-origin-height=&quot;311&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UI가 아닌 좀 더 쉽게 사용하려면 Twine을 설치한다. Twine은 Python 패키지를 PyPI 및 기타 저장소에 게시하기 위한 유틸리티이다.&lt;/p&gt;
&lt;pre id=&quot;code_1703774283281&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# pip install twine
# twine upload --repository-url http://nexusip:port/repository/pypi/&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;980&quot; data-origin-height=&quot;486&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mONvV/btsCN36o0CH/Jbmr0KnkjbRZJKr2pMTBjk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mONvV/btsCN36o0CH/Jbmr0KnkjbRZJKr2pMTBjk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mONvV/btsCN36o0CH/Jbmr0KnkjbRZJKr2pMTBjk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmONvV%2FbtsCN36o0CH%2FJbmr0KnkjbRZJKr2pMTBjk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;980&quot; height=&quot;486&quot; data-origin-width=&quot;980&quot; data-origin-height=&quot;486&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;upload 시 아래와 같은 경고가 발생하는 경우에는 deployment policy를 확인한다.&lt;br /&gt;
&lt;pre id=&quot;code_1703806085792&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; HTTPError: 400 Bad Request from http://10.140.0.111:30200/repository/pypi/
         Repository does not allow updating assets: pypi​&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;978&quot; data-origin-height=&quot;595&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c6yJD0/btsCJknRwGu/70XKpmcgrHFjxoFKDky2j0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c6yJD0/btsCJknRwGu/70XKpmcgrHFjxoFKDky2j0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c6yJD0/btsCJknRwGu/70XKpmcgrHFjxoFKDky2j0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc6yJD0%2FbtsCJknRwGu%2F70XKpmcgrHFjxoFKDky2j0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;773&quot; height=&quot;470&quot; data-origin-width=&quot;978&quot; data-origin-height=&quot;595&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
Deployment policy를 Allow redeploy 로 설정한다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;rest api로는 다음과 같이 호출한다.&lt;/p&gt;
&lt;pre id=&quot;code_1703816128958&quot; class=&quot;nginx&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;curl -v -u admin:admin -F &quot;pypi.asset0=@requests-2.31.0-py3-none-any.whl&quot; &quot;http://nexus/service/rest/v1/components?repository=pypi&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;b&gt;Download&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Nexus에서 패키지를 다운로드 하려면 구성 파일을&lt;span&gt;&amp;nbsp;&lt;/span&gt;pip편집해야 한다.&lt;/p&gt;
&lt;pre id=&quot;code_1703806988491&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$HOME/.config/pip/pip.conf

[global]
index = https://nexus/repository/pypi
index-url = https://nexus/repository/pypi/simple
no-cache-dir = false&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또는, 직접 nexus 주소를 입력할 수도 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1703807135842&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pip install --index-url http://nexus/repository/pypi/simple 패키지명&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;참고&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://help.sonatype.com/repomanager3/integrations/rest-and-integration-api/components-api&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://help.sonatype.com/repomanager3/&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://help.sonatype.com/repomanager3/integrations/rest-and-integration-api/components-api&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://help.sonatype.com/repomanager3/integrations/rest-and-integration-api/components-api&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Kubernetes/devops</category>
      <category>Nexus Pypi</category>
      <category>Pypi Repository</category>
      <category>Pypi 레포지토리</category>
      <author>kmaster</author>
      <guid isPermaLink="true">https://kmaster.tistory.com/179</guid>
      <comments>https://kmaster.tistory.com/179#entry179comment</comments>
      <pubDate>Fri, 29 Dec 2023 11:15:49 +0900</pubDate>
    </item>
    <item>
      <title>Kubernetes에 Nexus 설치</title>
      <link>https://kmaster.tistory.com/178</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;239&quot; data-origin-height=&quot;76&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/z23xc/btsCF7BIfzi/KFailmlG7rzDdkV4cNnook/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/z23xc/btsCF7BIfzi/KFailmlG7rzDdkV4cNnook/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/z23xc/btsCF7BIfzi/KFailmlG7rzDdkV4cNnook/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fz23xc%2FbtsCF7BIfzi%2FKFailmlG7rzDdkV4cNnook%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;327&quot; height=&quot;104&quot; data-origin-width=&quot;239&quot; data-origin-height=&quot;76&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #374151; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Sonatype Nexus는 소프트웨어 개발에서 사용되는 인기 있는 저장소 관리자 도구이다. 이는 소프트웨어 개발 프로세스에서 사용되는 바이너리 파일, 라이브러리 및 종속성과 같은 artifact를 관리하는 데 사용된다. Nexus는 이러한 artifact를 저장하고 검색하기 위한 중앙 저장소를 제공하여 개발 팀이 종속성을 관리하고 라이브러리를 공유하며 소프트웨어 빌드 프로세스의 일관성을 유지하는 데 도움을 준다.&lt;/p&gt;
&lt;p style=&quot;color: #374151; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #374151; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;개발자들은 Java개발 시 maven이나 gradle 컴파일 할 때 내부 Nexus 서버와 연동하여 jar 파일 등을 다운로드하거나 jar 를 deploy하는 형태로 많이 사용할 것이다. 특히 &lt;span style=&quot;color: #374151; text-align: start;&quot;&gt;폐쇄망 환경에서는 거의 필수로 사용된다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #374151; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #374151; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;하지만, Nexus는 이러한 빌드 도구와의 통합 외에도 다양한 기능을 제공하고 있다. ( 예를들어, Docker Registry의 기능도 포함하고 있다. )&lt;/p&gt;
&lt;p style=&quot;color: #374151; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #374151; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;b&gt;Sonatype Nexus의 주요 기능&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p style=&quot;color: #374151; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal; color: #374151; text-align: start;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;아티팩트 관리:&lt;/b&gt; Nexus는 바이너리 아티팩트(라이브러리, 프레임워크 등)를 저장하고 관리하기 위한 저장소로 사용&lt;/li&gt;
&lt;li&gt;&lt;b&gt;프록시 및 캐싱:&lt;/b&gt; Nexus는 외부 저장소의 프록시로 작동하며 아티팩트를 로컬로 캐싱한다. 이는 빌드 시간을 단축하고 외부 저장소 다운타임으로 인한 빌드 프로세스에 영향을 최소화하는 데 도움이 된다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;보안 및 액세스 제어:&lt;/b&gt; Nexus는 액세스 제어 및 보안 기능을 제공하여 관리자가 누가 아티팩트에 액세스하고 발행할 수 있는지 정의할 수 있다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;저장소 상태 확인:&lt;/b&gt; Nexus는 저장소에 대한 상태 확인을 수행하여 저장된 아티팩트에 문제가 있는지 식별하고 플래그를 지정할 수 있다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;빌드 도구와의 통합:&lt;/b&gt; Nexus는 Apache Maven, Gradle 등과 같은 인기 있는 빌드 도구와 원활하게 통합된다. 이 통합을 통해 빌드 도구는 빌드 프로세스 중에 Nexus 저장소에서 종속성을 검색할 수 있다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;여러 저장소 형식 지원:&lt;/b&gt; Nexus는 Maven, npm, Docker, NuGet 등과 같은 다양한 저장소 형식을 지원한다. 이 유연성은 Nexus를 다양한 프로젝트 및 생태계에서 사용할 수 있게 한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;아티팩트 검색 및 탐색:&lt;/b&gt; Nexus는 저장소에서 아티팩트를 검색하고 탐색할 수 있는 웹 인터페이스를 제공한다. 이를 통해 프로젝트에서 사용되는 종속성을 쉽게 찾고 이해할 수 있다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;b&gt;설치&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;kubernetes에 설치하는 방법은 helm 배포가 있다. 이번에는 단순 yaml로 배포해 보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1703769088400&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nexus-data
spec:
  storageClassName: openebs-hostpath
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
  volumeMode: Filesystem
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nexus
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nexus
  template:
    metadata:
      labels:
        app: nexus
    spec:
      containers:
      - image: sonatype/nexus3:3.63.0
        name: nexus
        ports:
        - containerPort: 8081
          protocol: TCP
        volumeMounts:
        - mountPath: /nexus-data
          name: nexus-data
      volumes:
      - name: nexus-data
        persistentVolumeClaim:
          claimName: nexus-data
---
apiVersion: v1
kind: Service
metadata:
  name: nexus-service
spec:
  ports:
  - name: nexus
    port: 8081
    protocol: TCP
    targetPort: 8081
    nodePort: 30200
  selector:
    app: nexus
  type: NodePort&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1566&quot; data-origin-height=&quot;585&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/V90HL/btsCLqAXPel/4RSSwgn5PQ9nZSoRwjSpT1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/V90HL/btsCLqAXPel/4RSSwgn5PQ9nZSoRwjSpT1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/V90HL/btsCLqAXPel/4RSSwgn5PQ9nZSoRwjSpT1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FV90HL%2FbtsCLqAXPel%2F4RSSwgn5PQ9nZSoRwjSpT1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1566&quot; height=&quot;585&quot; data-origin-width=&quot;1566&quot; data-origin-height=&quot;585&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #374151; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #374151; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;로그인을 시도할 때 admin 패스워드는 /nexus-data/admin.password 파일에 존재한다.&lt;/p&gt;
&lt;p style=&quot;color: #374151; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;502&quot; data-origin-height=&quot;353&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cgiC7z/btsCKSdtLXg/4YKDCDjLGkp48xWKPsssZk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cgiC7z/btsCKSdtLXg/4YKDCDjLGkp48xWKPsssZk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cgiC7z/btsCKSdtLXg/4YKDCDjLGkp48xWKPsssZk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcgiC7z%2FbtsCKSdtLXg%2F4YKDCDjLGkp48xWKPsssZk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;422&quot; height=&quot;297&quot; data-origin-width=&quot;502&quot; data-origin-height=&quot;353&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #374151; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #374151; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;로그인 후 다음과 같이 경고 메시지가 보인다.&lt;/p&gt;
&lt;pre id=&quot;code_1703769427063&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;The host system is allocating a maximum of 1 cores to the application. A minimum of 4 is recommended&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1559&quot; data-origin-height=&quot;393&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HeAWj/btsCF8nDDqZ/JWGoizpoJ0BH04aYFR3i11/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HeAWj/btsCF8nDDqZ/JWGoizpoJ0BH04aYFR3i11/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HeAWj/btsCF8nDDqZ/JWGoizpoJ0BH04aYFR3i11/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHeAWj%2FbtsCF8nDDqZ%2FJWGoizpoJ0BH04aYFR3i11%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1559&quot; height=&quot;393&quot; data-origin-width=&quot;1559&quot; data-origin-height=&quot;393&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #374151; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #374151; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Deployment.yaml 에 다음의 env를 추가하여 재기동하면 해결된다.&lt;/p&gt;
&lt;pre id=&quot;code_1703769763210&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;...
    spec:
      containers:
      - image: sonatype/nexus3:3.63.0
        name: nexus
        env:
        - name: INSTALL4J_ADD_VM_PARAMS
          value: &quot;-XX:ActiveProcessorCount=4&quot;
...&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #374151; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Kubernetes/devops</category>
      <category>NEXUS</category>
      <category>Nexus-public</category>
      <category>Snoatype Nexus</category>
      <category>넥서스</category>
      <author>kmaster</author>
      <guid isPermaLink="true">https://kmaster.tistory.com/178</guid>
      <comments>https://kmaster.tistory.com/178#entry178comment</comments>
      <pubDate>Fri, 29 Dec 2023 08:26:58 +0900</pubDate>
    </item>
    <item>
      <title>kubernetes apiserver 를 통해 Cluster 정보 조회</title>
      <link>https://kmaster.tistory.com/177</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;356&quot; data-origin-height=&quot;107&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cLSvzB/btsCF7tIMoa/TrF6w8yT7GH3boka1OoIq1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cLSvzB/btsCF7tIMoa/TrF6w8yT7GH3boka1OoIq1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cLSvzB/btsCF7tIMoa/TrF6w8yT7GH3boka1OoIq1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcLSvzB%2FbtsCF7tIMoa%2FTrF6w8yT7GH3boka1OoIq1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;356&quot; height=&quot;107&quot; data-origin-width=&quot;356&quot; data-origin-height=&quot;107&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;b&gt;인증 설정방법&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;0) 접근하는 API 서버 설정&lt;/p&gt;
&lt;pre id=&quot;code_1703513460131&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;KUBE_SERVER=$(kubectl config view -o jsonpath='{.clusters[0].cluster.server}')&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1) x.509 인증 방식으로 apiserver 접근 시 호출방법&lt;/p&gt;
&lt;pre id=&quot;code_1703512645261&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;curl --cert &amp;lt;path-to-cert-file&amp;gt; --key &amp;lt;path-to-key-file&amp;gt; --cacert &amp;lt;path-to-ca-file&amp;gt; \
$KUBE_SERVER/api/v1/pods&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2) token 정보를 활용하여 apiserver 접근 시 호출방법&lt;/p&gt;
&lt;pre id=&quot;code_1703512904324&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;curl --insecure --header &quot;Authorization: Bearer $KUBE_TOKEN&quot; $KUBE_SERVER/api/v1/pods&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;b&gt;API 사용예제&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 모든 pod list 호출방법&lt;/p&gt;
&lt;pre id=&quot;code_1703512829023&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;curl -k --cert 111.cert --key 111.key --cacert 111.ca \
-X GET https://$KUBE_SERVER/api/v1/pods&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- namespace안에&amp;nbsp; pod list 호출방법&lt;/p&gt;
&lt;pre id=&quot;code_1703513004435&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$KUBE_SERVER/api/v1/namespaces/$NAMESPACE/pods&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 모든 deployment list 호출방법&lt;/p&gt;
&lt;pre id=&quot;code_1703513527912&quot; class=&quot;bash&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;$KUBE_SERVER/api/v1/deployments&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Update&lt;/p&gt;
&lt;pre id=&quot;code_1703513832765&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ curl $KUBE_SERVER/api/v1/namespaces/default/deployments/sleep \
  --cacert 111.ca \
  --cert 111.cert \
  --key 111.key \
  -X PUT \
  -H 'Content-Type: application/yaml' \
  -d '---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sleep
spec:
  replicas: 1
  selector:
    matchLabels:
      app: sleep
  template:
    metadata:
      labels:
        app: sleep
    spec:
      containers:
      - name: sleep
        image: curlimages/curl
        command: [&quot;/bin/sleep&quot;, &quot;730d&quot;] 
'&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Patch&lt;/p&gt;
&lt;pre id=&quot;code_1703513915879&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ curl $KUBE_SERVER/api/v1/namespaces/default/deployments/sleep \
  --cacert 111.ca \
  --cert 111.cert \
  --key 111.key \
  -X PATCH \
  -H 'Content-Type: application/merge-patch+json' \
  -d '{
  &quot;spec&quot;: {
    &quot;template&quot;: {
      &quot;spec&quot;: {
        &quot;containers&quot;: [
          {
            &quot;name&quot;: &quot;sleep&quot;,
            &quot;image&quot;: &quot;curlimages/curl&quot;,
            &quot;command&quot;: [&quot;/bin/sleep&quot;, &quot;1d&quot;]
          }
        ]
      }
    }
  }
}'&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- DELETE&lt;/p&gt;
&lt;pre id=&quot;code_1703513958326&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ curl $KUBE_SERVER/api/v1/namespaces/default/deployments/sleep \
  --cacert 111.ca \
  --cert 111.cert \
  --key 111.key \
  - X DELETE&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- CRD&lt;/p&gt;
&lt;pre id=&quot;code_1703514095226&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;curl -k -X GET https://&amp;lt;kubernetes-api-server&amp;gt;/apis/&amp;lt;group&amp;gt;/&amp;lt;version&amp;gt;/&amp;lt;resource-plural&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Raw Mode&lt;/p&gt;
&lt;pre id=&quot;code_1703514019272&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl get --raw /api/v1/&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- openapi 사양 ( swagger 구문으로 표현 )&lt;/p&gt;
&lt;pre id=&quot;code_1703514739696&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kubectl get --raw /openapi/v2  &amp;gt; k8s-openapi-v2.json&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1827&quot; data-origin-height=&quot;930&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zl3PI/btsCyqog3I0/sYjqsQek33GCLC75tzwvKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zl3PI/btsCyqog3I0/sYjqsQek33GCLC75tzwvKk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zl3PI/btsCyqog3I0/sYjqsQek33GCLC75tzwvKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fzl3PI%2FbtsCyqog3I0%2FsYjqsQek33GCLC75tzwvKk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1827&quot; height=&quot;930&quot; data-origin-width=&quot;1827&quot; data-origin-height=&quot;930&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- openapi v3 사양&lt;/p&gt;
&lt;pre id=&quot;code_1703515291932&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/openapi/v3/&amp;lt;group&amp;gt;/&amp;lt;version&amp;gt;?hash=&amp;lt;HASH&amp;gt;

[example]
kubectl get --raw /openapi/v3/apis/apps/v1  &amp;gt; k8s-openapi-v3.json&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1840&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b9Fu9s/btsCDfS6mOG/QkClbdR4eaG4TUg06AKRM0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b9Fu9s/btsCDfS6mOG/QkClbdR4eaG4TUg06AKRM0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b9Fu9s/btsCDfS6mOG/QkClbdR4eaG4TUg06AKRM0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb9Fu9s%2FbtsCDfS6mOG%2FQkClbdR4eaG4TUg06AKRM0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1840&quot; height=&quot;1080&quot; data-origin-width=&quot;1840&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Kubernetes/일반</category>
      <category>access kubernetes apiserver</category>
      <category>curl kubernetes</category>
      <category>kubernetes apiserver restapi</category>
      <category>restful apiserver</category>
      <author>kmaster</author>
      <guid isPermaLink="true">https://kmaster.tistory.com/177</guid>
      <comments>https://kmaster.tistory.com/177#entry177comment</comments>
      <pubDate>Mon, 25 Dec 2023 23:43:03 +0900</pubDate>
    </item>
  </channel>
</rss>