<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>AOC55</title>
    <link>https://aoc55.tistory.com/</link>
    <description>aoc55.soft@gmail.com
github.com/aoc55</description>
    <language>ko</language>
    <pubDate>Mon, 15 Jun 2026 13:54:58 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>aoc55.soft@gmail.com</managingEditor>
    <image>
      <title>AOC55</title>
      <url>https://tistory1.daumcdn.net/tistory/2963497/attach/b9bb7dd9dada499294f0035bf28432fe</url>
      <link>https://aoc55.tistory.com</link>
    </image>
    <item>
      <title>독서 :: AGI, 천사인가 악마인가</title>
      <link>https://aoc55.tistory.com/79</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;458&quot; data-origin-height=&quot;672&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bL1A6u/dJMcabbMIJ4/ya3UT1Wo9KGOefT1l4KJn1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bL1A6u/dJMcabbMIJ4/ya3UT1Wo9KGOefT1l4KJn1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bL1A6u/dJMcabbMIJ4/ya3UT1Wo9KGOefT1l4KJn1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbL1A6u%2FdJMcabbMIJ4%2Fya3UT1Wo9KGOefT1l4KJn1%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;458&quot; height=&quot;672&quot; data-origin-width=&quot;458&quot; data-origin-height=&quot;672&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;div class=&quot;markdown-body&quot;&gt;
&lt;h1&gt;인상 깊은 내용&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;AI의 역사와 현재 국가 별 AI 전쟁상황&lt;/li&gt;
&lt;li&gt;AI -&amp;gt; AGI -&amp;gt; ASI.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;AGI는 반드시 등장할 것이다. 5년이나 50년이냐 시기의 차이일뿐.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;그리고 이 AGI의 학습능력 등은 사피엔스와 비교할 수 없을 수준일 것이다. ('시간에 대한 인식'조차 수준이 다르다)&lt;/li&gt;
&lt;li&gt;AGI 등장이후 인간(사피엔스)의 삶은 유토피아일까? 아니면 디스토피아일까?&lt;/li&gt;
&lt;li&gt;지구의 주인이 사피엔스에서 AI로 넘어가게 될까? 어쩌면 인류는 AI의 베타테스팅의 목적일수도.&lt;/li&gt;
&lt;li&gt;AGI를 국가 수준에서 통제할 수 있을까? 지금처럼 반세계화 정세에서는 불가능하다. 이미 사실상 불가능 한 것으로 보인다.&lt;/li&gt;
&lt;li&gt;그러면 국가 차원의 규제적으로 발전 방향, 속도 등이 통제가 불가능하다면 기술적으로 통제할 수 있을까?&lt;/li&gt;
&lt;li&gt;마지막으로 인공지능(AGI, ASI) 관점에서는 인간이 필요할까? 필요하다면 왜 필요할까? 인간의 뇌만 필요하지 않을까?&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;후기&lt;/h1&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;&lt;a href=&quot;https://youtu.be/QpBy2MZlvZw?si=qiSGOrLskl_dNu-8&quot;&gt;https://youtu.be/QpBy2MZlvZw?si=qiSGOrLskl_dNu-8&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;다만, 책 내용 자체는 앞부분(지난 몇십년간의 AI 발전 역사 등)을 제외하고는, 이미 시청한 유튜브 영상과 내용이 상당히 겹쳐 만약 영상을 다 보았다면 굳이 책은 안 사도 될 것 같다.&lt;/li&gt;
&lt;li&gt;결국 저자가 말하는 책의 핵심은&lt;b&gt;&lt;i&gt; &quot;&lt;/i&gt;&lt;span style=&quot;color: #000000;&quot;&gt;좋던 실던, 언제 오냐(5년 내에 올수도 있다)의 차이일뿐이지 AGI의 시대는 도래 할 것이다. 그리고 이후에는 엄청난 변화가 일어날 것이다. 그리고 그게 좋은 방향이냐, 나쁜 방향이냐 그건 아무도 예측할 수 없다, 다만 엄청난 변화가 올 것이다!&lt;/span&gt;&lt;i&gt;&quot;&lt;/i&gt;&lt;/b&gt;이다.&lt;/li&gt;
&lt;li&gt;이러한 핵심주제를 만들어 나가기 위해서, AI와 인류와 관련된 여러가지 이야기 (ex. 로마 기본소득 이야기, 일본 반려로봇 사례 등)를 중간중간 함께 풀어가서 다소 정신 없기도 했지만, 그만큼 여러 이야기를 가볍게 보기도 좋았다.&lt;/li&gt;
&lt;li&gt;그리고 (어쩌면 당연하지만) &quot;AGI가 등장할 것이니 ~ 이러니 어떻게 ~ 준비해라&quot; 등의 내용은 적혀 있지 않는다.&lt;/li&gt;
&lt;li&gt;어찌보면 당연하다. 이후의 삶을 누가 쉽사리 예상할 수 있겠는가?&lt;/li&gt;
&lt;li&gt;그래서 생각보다 얕은 내용과, 유튜브 내용과 겹치는 부분이 많아 책을 읽으면서 다소 당황 하기도 했지만, 쉽사리 짐작과 훈수를 두지 않는 책의 결말 부분은 깔끔한 것 같아 이 점은 만족스럽다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Life/독서</category>
      <category>agi</category>
      <category>AI</category>
      <category>Book</category>
      <category>책</category>
      <author>aoc55.soft@gmail.com</author>
      <guid isPermaLink="true">https://aoc55.tistory.com/79</guid>
      <comments>https://aoc55.tistory.com/79#entry79comment</comments>
      <pubDate>Fri, 2 Jan 2026 01:01:44 +0900</pubDate>
    </item>
    <item>
      <title>k8s :: PodDisruptionBudget (PDB)과 Disruption (#2)</title>
      <link>https://aoc55.tistory.com/78</link>
      <description>&lt;table style=&quot;color: #333333; text-align: start; border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #666666; text-align: left;&quot;&gt;개인적으로 공부하는 관점에서 작성한 내용이라, 잘못된 부분이 있을 수 있습니다. 발견 시 말씀주시면 감사하겠습니다.&lt;/span&gt;&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;723&quot; data-origin-height=&quot;702&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/l4O51/dJMb9YJ0OdV/l4DDg8pe4rHZV7wdbfXsP0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/l4O51/dJMb9YJ0OdV/l4DDg8pe4rHZV7wdbfXsP0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/l4O51/dJMb9YJ0OdV/l4DDg8pe4rHZV7wdbfXsP0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fl4O51%2FdJMb9YJ0OdV%2Fl4DDg8pe4rHZV7wdbfXsP0%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;259&quot; height=&quot;251&quot; data-origin-width=&quot;723&quot; data-origin-height=&quot;702&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;div class=&quot;markdown-body&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;b&gt;이전편&lt;/b&gt;&lt;/u&gt;: &lt;a href=&quot;https://aoc55.tistory.com/77&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://aoc55.tistory.com/77&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;PodDisruptionBudget (PDB)&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PDB가 어떠한 상황에 필요한지 먼저 알아보았으니, 이제 PDB에 대해 좀더 알아보자.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;PodDisruptionBudget 선언 예시&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;아래는 PDB를 선언하는 예시 YAML 파일이다.&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: rabbitmq-disruption-budget
  namespace: openstack
spec:
  maxUnavailable: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: openstack&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;상세 스펙은 공식 문서(&lt;a href=&quot;https://kubernetes.io/docs/tasks/run-application/configure-pdb/&quot;&gt;https://kubernetes.io/docs/tasks/run-application/configure-pdb/&lt;/a&gt;) 를 참고하자.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 한번 PDB를 한줄로 정의하면 &quot;&lt;b&gt;Cluster 위에서 실행되는 워크로드가, 빈번하게 발생하는 자발적인 중단에 대해서 HA(highly availablity)를 보장하기 위한 도구&lt;/b&gt;&quot;라고 정의할 수 있을 것 같다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Eviction API 와 PDB&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 특정 워크로드에 대해 PDB를 선언한 경우, Node Drain 등에 의해 발생하는 &lt;code&gt;Evicition API&lt;/code&gt;  요청에 대해, 위와 같이 선언한 &lt;b&gt;PDB와 현재 상태에 따라서 Pod Evcition이 허용되거나 거부되는 구조&lt;/b&gt;이다. 즉, PDB는 Evcition API와 연관성이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좀 더 예시를 들어보면, 서비스 특성 상 최소한 개수(혹은 퍼센테이지)를 보장해줘야 하는 Pod들이 있는데, 이때 PDB 선언을 통해 클러스터 관리자가 Node Drain을 통해 Eviction 을 하더라도, 워크로드 서비스 관점에서 이를 방어(?)하여 서비스가 살아 있을 수 있도록 하는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 PDB는 Node drain 등이 사용하는 &quot;Eviction API&quot;와 상관이 있는 것이기 때문에, Eviction API 기반이 아닌 Pod Delete 등이 PDB 에 의해 거절되거나 하지는 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 어떻게 보면 PDB는 Eviction을 제어하는 정책이라고도 볼 수 있다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Restart(Rolling Update) 와 PodDisruptionBudget 간의 관계&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞에서 Pod Delete(ex. &lt;code&gt;kubectl delete pod ...&lt;/code&gt;) 등의 경우에는 PDB의 영향을 받지 않는다고 말하였다. 그러면 Statefulset/Deployment와 같은 컨트롤러 기반의 리소스들의 &lt;b&gt;Restart&lt;/b&gt;는 PDB와 어떠한 관계가 있을까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;결론적으로 Depoyments/Statuefulset 의 Restart 역시도 PDB가 Restart를 막는 구조는 아니다.&lt;/b&gt; 즉, PDB로 설정한다 하더라도 컨트롤러의 롤링 업데이트를 막거나 할 수는 없다. 해당 Rolling Update에 대한 전략은 PDB가 아닌 Deployements, Statefulset에 선언된 대로 철저히 수행이 된다. (ex. &lt;code&gt;spec.strategy.rollingUpdate.maxUnavailable&lt;/code&gt;, &lt;code&gt;spec.strategy.rollingUpdate.maxSurge&lt;/code&gt;, ...)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜인지 생각해보면 Controller가 있는 Resource 들의 Rolling Update 방식은, 새로 Controller를 생성해서 관련 리소스를 Create 한 뒤 =&amp;gt; 이전 컨트롤러에 매핑된 리소스를 Delete 하는 구조이다. 즉, Evcition API 방식이 아니다. (이전 Node Drain과 는 다른 방식이다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만, 그래도 Contoller에 의해 Restart 과정에서 발생하는 Pod 종료 등에 대해서는 PDB 설정 내역에 &quot;Counting(반영)&quot;은 된다. 따라서 만약 Restart 과정에서 동시에 node drain 이 요청 온다던가 하는 경우에 &quot;Counting 등이 반영된 PDB&quot;에 의해 Eviction API에 대한 '거절 및 방지' 역할은 할 수 있다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;간단한 PodDisruptionBudget 동작 시나리오&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상세한 시나리오는 공식문서 내 &lt;a href=&quot;https://kubernetes.io/docs/concepts/workloads/pods/disruptions/#pdb-example&quot;&gt;https://kubernetes.io/docs/concepts/workloads/pods/disruptions/#pdb-example&lt;/a&gt; 에서 참고하자.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아주 간단한 시나리오를 살펴보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;사전 전제사항&lt;/b&gt;으로 Node 별로 Pod가 1개씩 배치되어 있고, PDB 설정에 &lt;code&gt;maxUnavailable:1&lt;/code&gt; 로 설정되어 있는 상태이다.&lt;/p&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;node1
- pod-a-1

node2
- pod-a-2

node3
- pod-a-3

---
now Unavailable:0&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 &lt;code&gt;node1&lt;/code&gt; 에 대해서 &lt;b&gt;node drain&lt;/b&gt; 을 수행하게 되면, node1에 있던 &lt;code&gt;pod-a-1&lt;/code&gt;이 다른 Node에 배치될 것이다. 그리고 이 과정중에서는 &lt;code&gt;Unavailable: 1&lt;/code&gt; 로 증가하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 (node1에서 Eviction 된) Pod가 다른 Node에서 기동이 완료되기 이전에, &lt;b&gt;또 다른 node에 대해 바로 Eviction 을 수행하게 되면?&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;node1 (drain)

node2 &amp;lt;----- Drain(Eviction) 시도
- pod-a-2

node3
- pod-a-3 
- pod-a-4 (아직 기동중)

---
now Unavailable:1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 node3로 대피한 Pod가 기동이 완료지 않음으로 아직 &lt;code&gt;Unavailable: 1&lt;/code&gt; 인 상태이고, 이는 &lt;b&gt;곧 사전 설정된 PDB&lt;/b&gt; (&lt;code&gt;maxUnavailable:1&lt;/code&gt;) &lt;b&gt;에 의해&lt;/b&gt;, &lt;code&gt;node2&lt;/code&gt;&lt;b&gt;에 대한 Evcition은 거절된다!&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 &lt;code&gt;node3&lt;/code&gt; 에서 Pod 생성이 완료 되고 이에 따라 &lt;code&gt;maxUnavailable: 0&lt;/code&gt;으로 내려간 뒤, 다시 &lt;code&gt;node2&lt;/code&gt;에 대해 drain 을 요청하면 성공할 수 있다.&lt;/p&gt;
&lt;pre class=&quot;asciidoc&quot;&gt;&lt;code&gt;node1 (drain)

node2 (drain)

node3
- pod-a-3
- pod-a-4 
- pod-a-5
---
now Unavailable:0&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&quot;Role&quot; 과 PodDisruptionBudget ?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PDB와 관련해서 kubernetes 공식 문서에서는 &lt;b&gt;PDB가 실제 Role 간의 '인터페이스'로 동작&lt;/b&gt;한다고 적어놨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이게 무슨 의미인가 하니, 대부분 클러스터에서 워크로드가 실행되는 경우 &quot;&lt;b&gt;워크로드 관리자&lt;/b&gt;&quot;와 &quot;&lt;b&gt;클러스터가 관리자&lt;/b&gt;&quot;가 각각의 Role로 나누어져 있는 경우가 보통이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 이 상태에서 클러스터 관리자가 클러스터 관리를 위한 작업(ex. Node의 버전 업그레이드 등을 위한  Node drain 수행)을 진행하다고 할때, 워크로드 관리자는 서비스에 PDB를 적절하게 선언하는 방식을 통해 앞서 말한 클러스터 관리자의 작업(ex. Node Drain)이 임의적으로 수행되는 것을 방지할 수도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, &quot;클러스터 관리의 영역&quot;과 &quot;워크로드 서비스 관리의 영역&quot;에 대해서 PDB 선언을 통해서 인터페이스화(?) 하였다는 의미이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;끝.&lt;/p&gt;
&lt;/div&gt;</description>
      <category>Cloud/kubernetes (k8s)</category>
      <category>cloud</category>
      <category>k8s</category>
      <category>Kubernetes</category>
      <category>pdb</category>
      <author>aoc55.soft@gmail.com</author>
      <guid isPermaLink="true">https://aoc55.tistory.com/78</guid>
      <comments>https://aoc55.tistory.com/78#entry78comment</comments>
      <pubDate>Sat, 18 Oct 2025 23:23:52 +0900</pubDate>
    </item>
    <item>
      <title>k8s :: PodDisruptionBudget (PDB)과 Disruption (#1)</title>
      <link>https://aoc55.tistory.com/77</link>
      <description>&lt;table style=&quot;color: #333333; text-align: start; border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #666666; text-align: left;&quot;&gt;개인적으로 공부하는 관점에서 작성한 내용이라, 잘못된 부분이 있을 수 있습니다. 발견 시 말씀주시면 감사하겠습니다.&lt;/span&gt;&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;723&quot; data-origin-height=&quot;702&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQKO0o/dJMb9OUZ2Wo/Tpi5dbaV1JmMt2u1Wo0zj0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQKO0o/dJMb9OUZ2Wo/Tpi5dbaV1JmMt2u1Wo0zj0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQKO0o/dJMb9OUZ2Wo/Tpi5dbaV1JmMt2u1Wo0zj0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQKO0o%2FdJMb9OUZ2Wo%2FTpi5dbaV1JmMt2u1Wo0zj0%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;256&quot; height=&quot;249&quot; data-origin-width=&quot;723&quot; data-origin-height=&quot;702&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;div class=&quot;markdown-body&quot;&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에서 &lt;code&gt;v1.21&lt;/code&gt; 이후부터 제공되는 &lt;b&gt;PodDisruptionBudget(이하 PDB)&lt;/b&gt; 에 대해 알아보도록 하자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 kubernetes 내에 제공하는 &quot;PDB&quot; 라는 '기능'에 대해 단순히 알아보려다가, 이게 &quot;왜 필요한지?&quot;부터 쫓아가다보니 깊게 생각해야 하는 요소들이 많아서 아래와 학습한 내용 등을 정리한다.&lt;/p&gt;
&lt;h1&gt;Disruption (중단)과 대응 그리고 PDB&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 쉽게 말하면 PDB는, kuberntes 위에서 동작되는 워크로드들에 대해 &lt;b&gt;가용성(HA)&lt;/b&gt; 을 보장하기 위해 제공하는 기능이라고 이해하면 된다. (물론 이 한줄로만은 이해가 쉽지 않다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 PDB를 이해하려면, 결국 kubernetes에서 &lt;b&gt;Disruption(중단)&lt;/b&gt; 에 대해 먼저 알고 있어야 한다. 따라서 먼저 kubernetes 상에서 &quot;Disruption&quot;에 대한 의미를 먼저 알아보자.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;자발적인 중단, 비자발적인 중단&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Disruption을 한국어로 번역하면 말 그대로 '&lt;b&gt;중단&lt;/b&gt;'이다. 그리고 이 '중단'은 다시 &lt;b&gt;자발적인 중단(voluntary disruptions)&lt;/b&gt; 과 &lt;b&gt;비자발적인 중단(involuntary disruptions)&lt;/b&gt; 으로 나눠서 구분할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 '&lt;b&gt;비자발적인 중단&lt;/b&gt;'의 경우 관리자 등에 의해 의도적이 아닌, &lt;b&gt;쉽게 말해 '장애' 상태로&lt;/b&gt; 예를 들어보면 Node 역할을 하는 Hardware의 물리적인 Failure, 커널 패닉,  네트워크 단절 등이 예가 될 수 있을 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반면 '&lt;b&gt;자발적인 중단&lt;/b&gt;'의 경우 애플리케이션 소유자 or 클러스터 관리자 등에 의해 &lt;b&gt;의도적으로 수행하는 작업 등으로 인해 발생하는 중단&lt;/b&gt;이다. 만약 '애플리케이션 소유자'에 의해 발생하는 '중단'의 예시로는 당연하게도 Pod Restart, Update, Delete 등이 있을 수 있다. '클러스터 관리자'에 의해 발생하는 '중단'의 경우에는 클러스터 및 노드 레벨로서, 예를 들어보면 OS 패키지 업그레이드, 네트워크 작업 등을 꼽을 수 있다. 다만 이경우에는 대부분 필연적으로 &quot;작업 대상 Node 의 Drain&quot; 을 선행하게 된다. (그리고 이게 PDB와 관련이 있다!)&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;중단에 '대응'하기 (with PDB)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 이제 이러한 자발적 혹은 비자발적 '중단'에 &lt;b&gt;'잘' 대응하는 워크로드를 구성&lt;/b&gt;하기 위해서 알아보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저, 사실 '비자발적 중단'의 경우 의도적이지 않은 사실상 &quot;예측할 수 없는 장애의 상황&quot;으로서 완전히 막을 수는 없다. 다만 이러한 상황 등을 &lt;b&gt;'완화'하기 위해서는&lt;/b&gt; Pod 레벨에서 동작이 필요한 리소스를 보장하고, 워크로드를 HA 구조로 배포하기, Anti Affinity 와 AZ와 같은 스케줄링 전략을 가지고 워크로드를 잘 구성하는 등의 전략과 실행이 필요한 영역이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반면 '자발적인 중단'의 경우에는, 이 글의 주제인 'PDB'와 관련이 있다. 하지만 그 전에, 일단 워크로드가 실행되는 Kubernetes Cluster가 &quot;어떤 기반의 Cluster 인가?&quot;에 따라 PDB의 필요성 자체가 없을 수도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어, On-Premise 환경(혹은 순수한 kubernetes)에서는 별도로 클러스터 관리자가 구성하지 않았다는 가정하에 &quot;자동화 된 자발적인 중단&quot;이 딱히 없다. 다르게 말하면 자동으로 Node가 Drain 될 일이 없다. (장애와 같은 '비자발적인 중단' 제외) 그렇기 때문에 별도로 자발적 중단에 대해 계획하기 전까지, PDB 구성이 딱히 필요하지 않을 수도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만, '자발적인 중단'이 꼭 클러스터 관리자에 의한 수동으로 Node drain 만 의미하는 것이 아니며, 각각의 클러스터의 운영 정책과 이에 따른 자동화 작업과 같이 &quot;언제든지 발생할 수 있는 이벤트&quot;이다. 따라서 비록 On-Premise 환경의 kubernetes 라 하더라도 중요한 운영 환경인 경우 등에 PDB의 구성이 필요할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반면에 kubernetes Cluster가 EKS와 같은 &quot;Managed 클러스터&quot;에 실행된다면, Cloud 공급자(ex. AWS, GCP)에 의해 자동적으로 자발적 중단이 발생할 수 있다. (ex. Node의 OS 업데이트, kubelet 업데이트)&lt;br /&gt;물론 이러한 경우 Cloud 공급자들은 언제 이러한 중단이 발생하는지에 대해 문서화를 잘 해서, 해당 클러스터 관리지와 워크로드 담당자들이 이를 잘 대비할 수 있게 해야 한다. 그리고 바로 이때 워크로드의 가용성 등을 대비하기 위해서 본 글의 주요 목적인 &quot;&lt;b&gt;PDB&lt;/b&gt;&quot; 구성이 필요한 것이다.&lt;/p&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;다음편 ::&lt;/b&gt; &lt;a href=&quot;https://aoc55.tistory.com/78&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://aoc55.tistory.com/78&lt;/a&gt;&lt;/p&gt;</description>
      <category>Cloud/kubernetes (k8s)</category>
      <category>cloud</category>
      <category>k8s</category>
      <category>Kubernetes</category>
      <category>pdb</category>
      <author>aoc55.soft@gmail.com</author>
      <guid isPermaLink="true">https://aoc55.tistory.com/77</guid>
      <comments>https://aoc55.tistory.com/77#entry77comment</comments>
      <pubDate>Sat, 18 Oct 2025 23:18:49 +0900</pubDate>
    </item>
    <item>
      <title>Openstack :: Nova Cell 이란?</title>
      <link>https://aoc55.tistory.com/76</link>
      <description>&lt;table style=&quot;color: #333333; text-align: start; border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #666666; text-align: left;&quot;&gt;개인적으로 공부하는 관점에서 작성한 내용이라, 잘못된 부분이 있을 수 있습니다. 발견 시 말씀주시면 감사하겠습니다.&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;500&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EUvgb/dJMb83EzilJ/lUFBDTLfTPtaXgVbgrBKGk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EUvgb/dJMb83EzilJ/lUFBDTLfTPtaXgVbgrBKGk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EUvgb/dJMb83EzilJ/lUFBDTLfTPtaXgVbgrBKGk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEUvgb%2FdJMb83EzilJ%2FlUFBDTLfTPtaXgVbgrBKGk%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;600&quot; height=&quot;500&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;500&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;div class=&quot;markdown-body&quot;&gt;
&lt;h1&gt;Nova Cell&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 회사 환경에서 &quot;복수의 Cell 구조&quot;로 Nova Cell 을 활용하지는 않지만, 그래도 잘 모르고 있는&lt;b&gt; Nova의 Cell&lt;/b&gt; 에 대해 정확히 알고 있어야 할 것 같아서 아래와 같이 학습과 스스로 생각한 내용을 정리한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글 보다 더 정확한 내용 등은 Nova 공식문서 내&amp;nbsp; &lt;a href=&quot;https://docs.openstack.org/nova/latest/admin/cells.html&quot;&gt;Cells (v2) &amp;mdash; nova 32.1.0.dev43 documentation&lt;/a&gt; 에서 확인 할 수 있을 것 같다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Cell 의 개념&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Nova 에서 &quot;Cell&quot; 이라는 것은 &lt;b&gt;운영 관점&lt;/b&gt;에서 Compute Node들을 논리적으로 그룹화한 단위이며, Cell의 가장 큰 특징은 &lt;b&gt;Cell 별로 독립적인 Database와 Queue 기반으로 동작한다는 것이다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같의 Cell 구현의 가장 중요한 목적은 만약 Compute Node가 증가 시, 필연적으로 같이 증가하게 되는 Database 및 Queue 사용량(부하)에 대해 &quot;&lt;b&gt;Cell&quot; 이라는 그룹으로 격리를 한 뒤, 각각의 Database &amp;amp; Queue 구성하는 방식을 통해 부하 분산과 함께 장애 혹은 작업(수평 확장 등) 등에 서로 영향을 받지 않게 하는 등의 효율적으로 운영 및 관리를 하기 위함&lt;/b&gt;으로 보인다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Cell? Host Aggreate?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 Nova 뿐만 아니라 Openstack 에서는 &lt;b&gt;Region&lt;/b&gt; 과 &lt;b&gt;AZ&lt;/b&gt; 및 Nova 에서는 &lt;b&gt;Host Aggretage&lt;/b&gt; 라는 컨셉이 이미 있다. 이러한 컨셉들과 &lt;b&gt;Cell&lt;/b&gt; 간엔 무슨 관계 혹은 차이가 있는 것일까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 먼저 &quot;&lt;b&gt;Region&quot;&lt;/b&gt;은 Nova와 같은 컴포넌트 수준이 아닌, Openstack 클러스터 레벨의 설정이다. 즉, 사실상 하나의 Region은 하나의 Openstack Cluster 라고 볼 수 있다. 그렇기에 각각의 Openstack 리전은 근본적으로 완전히 별도의 API Endpoint, Database, RabbitMQ 등을 구성한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 다음으로 &quot;&lt;b&gt;AZ&quot;&lt;/b&gt;의 경우 사실 Openstack을 사용할 때 중요한 요소인 &quot;사용자 등에게 가용성을 표현하는 논리적인 구분&quot;이다. 여기서 Openstack 에서 AZ를 설정 한다는 것은, 사전에 가용성 등이 반영된 물리적인 하드웨어 등을 구성 배치한 후, 이를 Openstack 상에서 &quot;AZ&quot;라는 개념을 통해 논리적인 의미로 표현하는 것이다. (당연히도) 하나의 Region 안에 여러 개의 AZ를 구성할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로 Nova에 존재하는 &quot;&lt;b&gt;Host Aggregate&quot;&lt;/b&gt;는 Openstack Nova의 구성과 관련된 설정보다는 아키텍처보다는, Host를 그룹화 해서 스케줄링을 통해 'VM들을 배치하기 위한 스케줄링'을 정밀하게 제어하기 위한 목적이다. 따라서 운영관리 등을 위한 Cell 과는 결이 다르다고 볼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 위 요소들과 &quot;Cell&quot;을 비교하면, Cell은 &quot;Nova&quot; 라는 컴포넌트들을 안정적으로 '운영 및 관리'를 위한 그룹핑 단위로서, VM 스케줄링을 위한 Host Aggregate 등과는 목적 자체가 다른 것으로 생각할 수 있을 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로 관계를 정리해보면, (Openstack) Region 하위에 Nova Cell 이 있고 -&amp;gt; 이제 Nova Cell 내에서 AZ를 설정할 수 있으며 -&amp;gt; AZ와 연관된 Host Aggregate를 구성할 수 있다. 물론 이는 오직 단위로서만 크기 순으로 정렬한 것으로,&lt;b&gt; 필요성과 사용목적 등이 위에 언급했듯이 애초에 각기 다르기 때문에 개별적으로 각각의 목적과 필요성 등을 먼저 고민해야 할 것 같다.&lt;/b&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Cell 의 종류&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Cell 의 경우 기본적으로 Cell 0와 Cell 1, Cell 2.. 과 같은 두가지 계층으로 나누어진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Cell0&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;스케줄링에 실패한 인스턴스 등을 저장하는 특수한 Cell.&lt;/li&gt;
&lt;li&gt;실제 컴퓨트 리소스가 있는 것은 아니다.&lt;/li&gt;
&lt;li&gt;스케줄링 실패 시 인스턴스가 삭제되지 않고 기록을 남기기 위해 사용된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Cell N (ex. Cell 1, Cell 2, ...)&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;실제 Compute Node가 속한 Cell이다.&lt;/li&gt;
&lt;li&gt;Cell 마다 독립적인 nova-compute 와 Database, Message Queue 를 사용한다.&lt;/li&gt;
&lt;li&gt;각 Cell 간은 서로 직접적으로 통신하지 않으며, 서로의 상태에 영향을 미치지도 않는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 Cell 을 설정했을 때 Nova Component 에 대한 아키텍처를 확인해 보자&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Cell 을 포함한 Nova 아키텍처&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그림의 출처는 &lt;a href=&quot;https://docs.openstack.org/nova/latest/admin/cells.html&quot;&gt;https://docs.openstack.org/nova/latest/admin/cells.html&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Single Cell 기반&lt;/b&gt;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1228&quot; data-origin-height=&quot;644&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/byNirk/dJMb9PM80CC/KeGjYyMmjbWVj6suUVCwZK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/byNirk/dJMb9PM80CC/KeGjYyMmjbWVj6suUVCwZK/img.png&quot; data-alt=&quot;단일 Cell 사용 시&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/byNirk/dJMb9PM80CC/KeGjYyMmjbWVj6suUVCwZK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbyNirk%2FdJMb9PM80CC%2FKeGjYyMmjbWVj6suUVCwZK%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;1228&quot; height=&quot;644&quot; data-origin-width=&quot;1228&quot; data-origin-height=&quot;644&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;단일 Cell 사용 시&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;특수한 &lt;code&gt;Cell 0&lt;/code&gt; 말고, 일반적인 &lt;code&gt;Cell&lt;/code&gt; 을 오직 한 개만 사용 하였을 때의 구조이다.&lt;/li&gt;
&lt;li&gt;참고로 &lt;code&gt;Cell 0&lt;/code&gt; 역시 별도의 Database 를 사용하는 것을 알 수 있다. (단, MQ는 사용하지 않는다)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;복수의 Cell 기반&lt;/b&gt;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2010&quot; data-origin-height=&quot;1120&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uK8tq/dJMb9NBNiP4/BKK4udzfNCchX1F59Ou6fK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uK8tq/dJMb9NBNiP4/BKK4udzfNCchX1F59Ou6fK/img.png&quot; data-alt=&quot;복수 Cell 사용 시&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uK8tq/dJMb9NBNiP4/BKK4udzfNCchX1F59Ou6fK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuK8tq%2FdJMb9NBNiP4%2FBKK4udzfNCchX1F59Ou6fK%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;2010&quot; height=&quot;1120&quot; data-origin-width=&quot;2010&quot; data-origin-height=&quot;1120&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;복수 Cell 사용 시&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;특수한 &lt;code&gt;Cell 0&lt;/code&gt; 말고, 일반적인 &lt;code&gt;Cell&lt;/code&gt; 을 2개 (&lt;code&gt;Cell 1&lt;/code&gt;, &lt;code&gt;Cell 2&lt;/code&gt;)를 사용하였을 때 구조이다.&lt;/li&gt;
&lt;li&gt;보면 알 수 있듯이 &lt;code&gt;Cell 1&lt;/code&gt;과 &lt;code&gt;Cell 2&lt;/code&gt;이 별도의 Cell Database 과 Cell MQ 구성 사용하는 것을 알 수 있다.&lt;/li&gt;
&lt;li&gt;이에 따라 &lt;code&gt;nova-compute&lt;/code&gt;의 요청을 받아, 실제 각각의 Cell Database와 통신 역할을 하는 &lt;code&gt;nova-conductor&lt;/code&gt; 역시도 분리되어 있음을 알 수 있다.&lt;/li&gt;
&lt;li&gt;참고로 API Server와 스케줄러 등은 Cell 내 종속적이지 않는 요소들로 별개의 Database와 MQ 구성을 가지고 있으며 이는 Cell의 개수와 무관하다.&lt;/li&gt;
&lt;li&gt;다만, Cell 이 증가함에 따라 상위에 Super Conductor 라는 개념이 등장한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Cell 확인해보기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실습하는 환경은 기본적인 Cell만 설치된 환경이다. (즉, 특수 Cell 인 &lt;code&gt;cell0&lt;/code&gt;와 일반 Cell 인 &lt;code&gt;cell1&lt;/code&gt;만 존재)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;먼저 Cell 목록을 조회해보자.&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;smali&quot;&gt;&lt;code&gt;nova-manage cell_v2 list_cells&lt;/code&gt;&lt;/pre&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3154&quot; data-origin-height=&quot;214&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cfXc93/dJMb9NIyERj/OdYPzp7wIqusBdMz0GLKrk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cfXc93/dJMb9NIyERj/OdYPzp7wIqusBdMz0GLKrk/img.png&quot; data-alt=&quot;Cell 리스트 조회&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cfXc93/dJMb9NIyERj/OdYPzp7wIqusBdMz0GLKrk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcfXc93%2FdJMb9NIyERj%2FOdYPzp7wIqusBdMz0GLKrk%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;3154&quot; height=&quot;214&quot; data-origin-width=&quot;3154&quot; data-origin-height=&quot;214&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Cell 리스트 조회&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;cell0&lt;/code&gt;, &lt;code&gt;cell1&lt;/code&gt; 을 확인할 수 있으며, 각각의 별개로 구성된 MQ와 Database 구성 및 상태 등을 확인 할 수 있다.&lt;/li&gt;
&lt;li&gt;참고로 특수 Cell 인 &lt;code&gt;cell0&lt;/code&gt;은 MQ를 사용하지 않는 것을 알 수 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이후 Cell 에 할당된 Compute Host 목록을 조회해보자.&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;smali&quot;&gt;&lt;code&gt;nova-manage cell_v2 list_hosts&lt;/code&gt;&lt;/pre&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;944&quot; data-origin-height=&quot;212&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TN2N5/dJMb9NIyEQ9/f4Ow5kPoMZbtawMPMDw1Z1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TN2N5/dJMb9NIyEQ9/f4Ow5kPoMZbtawMPMDw1Z1/img.png&quot; data-alt=&quot;Cell 내 Host 조회&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TN2N5/dJMb9NIyEQ9/f4Ow5kPoMZbtawMPMDw1Z1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTN2N5%2FdJMb9NIyEQ9%2Ff4Ow5kPoMZbtawMPMDw1Z1%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;944&quot; height=&quot;212&quot; data-origin-width=&quot;944&quot; data-origin-height=&quot;212&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Cell 내 Host 조회&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기본 Cell 인 &lt;code&gt;cell1&lt;/code&gt; 에 할당된 Compute Host 목록을 확인 할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;추가로 Openstack 이 사용중인 Database 목록을 조회하면 아래와 같이 확인할 수 있다.&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;gherkin&quot;&gt;&lt;code&gt;mysql&amp;gt; show databases;
+---------------------+
| Database            |
+---------------------+
| barbican            |
| cinder              |
| glance              |
| information_schema  |
| keystone            |
| mariadb             |
| mysql               |
| neutron             |
| nova                |   # ----&amp;gt; cell1 전용
| nova_api            |   # ----&amp;gt; API Server 전용
| nova_cell0          |   # ----&amp;gt; cell0 전용
| octavia             |
| octavia-persistence |
| performance_schema  |
| placement           |
| skyline             |
| sys                 |
+---------------------+&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;끝.&lt;/p&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Cloud/Openstack</category>
      <category>cloud</category>
      <category>Nova</category>
      <category>openstack</category>
      <author>aoc55.soft@gmail.com</author>
      <guid isPermaLink="true">https://aoc55.tistory.com/76</guid>
      <comments>https://aoc55.tistory.com/76#entry76comment</comments>
      <pubDate>Sat, 18 Oct 2025 22:31:24 +0900</pubDate>
    </item>
    <item>
      <title>k8s :: k8s Security - 10 Best Practices</title>
      <link>https://aoc55.tistory.com/75</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 18px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 100%; height: 18px; text-align: center;&quot;&gt;아래 Youtube 영상을 보고 개인적으로 정리한 내용입니다.&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;div class=&quot;markdown-body&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://youtu.be/oBf5lrmquYI?si=Ltcd7YUFGa0nYNY1&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtu.be/oBf5lrmquYI?si=Ltcd7YUFGa0nYNY1&lt;/a&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=oBf5lrmquYI&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/U5HIv/hyZJ4Cu9eX/b89yhqVIakR4wRVcIL2Uhk/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=1030_130_1190_304,https://scrap.kakaocdn.net/dn/evXb8p/hyZJWR1fTH/ej914XSGq8WbDAabXelZhK/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=1030_130_1190_304&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;Kubernetes Security Best Practices you need to know | THE Guide for securing your K8s cluster!&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/oBf5lrmquYI&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;kubernetes의 워크로드를 올리는 관점 외, &lt;b&gt;Cluster의 Security 관점&lt;/b&gt;에서 아래와 같이 10가지 주제를 간단히 소개하고 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Intro (Cloud 와 Security)&lt;/h1&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;723&quot; data-origin-height=&quot;702&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ND1YX/dJMb85I7bVl/q8jFNH9S6FmVcg4Kb5w1G1/tfile.svg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ND1YX/dJMb85I7bVl/q8jFNH9S6FmVcg4Kb5w1G1/tfile.svg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ND1YX/dJMb85I7bVl/q8jFNH9S6FmVcg4Kb5w1G1/tfile.svg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FND1YX%2FdJMb85I7bVl%2Fq8jFNH9S6FmVcg4Kb5w1G1%2Ftfile.svg&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;215&quot; height=&quot;209&quot; data-origin-width=&quot;723&quot; data-origin-height=&quot;702&quot;/&gt;&lt;/span&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;대부분의 워크로드들이 &quot;Cloud&quot;로 이동하는 트렌드 속에서, 빈번하게 발생하는 오해 중 하나가 &quot;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;기본적으로 Cloud는 안전하다고 생각하는 점&lt;/span&gt;&lt;/b&gt;&quot;이다. 이는 &quot;오해&quot;이며, &lt;b&gt;워크로드가 비록 &quot;Cloud&quot;위 에 있다고 해도 Security 는 기존의 On-Premise와 동일한 수준으로 유지해야 한다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Security는 &lt;b&gt;Multiple Protection Mechansim x On Multi Levels 의 조합&lt;/b&gt;으로 애초에 한두가지 기술로 해결할 수 없는 분야이다.&lt;br /&gt;예를 들어, kubernetes 환경 위에서 Application Workload를 실행 한다고 하면 &lt;i&gt;(1) Underyling Infrastrucutre&lt;/i&gt;, &lt;i&gt;(2) Kubernetes Level&lt;/i&gt;, &lt;i&gt;(3) Application Level &lt;/i&gt;으로 나눌 수 있으며, 모든 (1)~(3) 레벨에서 보안을 신경써야 한다. 또한 개발 영역에서는 코드의 '반복'을 좋지 않은 것으로 여기지만, 반대로 보안의 분야에서는 반복이 필수이다.&lt;br /&gt;마지막으로 Security 분야의 또 다른 특 중 하나로 공격자(해커)가 매우 유리할 수 밖에 없다. 공격자는 딱 '1개'의 Security Weak Link만 찾아도 되기 때문이다.&lt;/p&gt;
&lt;h1&gt;Kubernetes Security 10 Best Practices&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 kubernetes Cluster 관점 에서 Security와 관련된 10가지 Best Practices를 알아보자.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 안전한 Container Image 사용과 Image Scanning 도입하자&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 취약점이 있는 Image 를 사용하고 해당 Image로 실행된 Container를 공격자에게 탈취될 경우, Container 뿐만 아니라 Host의 Volume, File System, Kubelet Config 등을 공격까지 당할 위험이 도사리고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 아래와 같은 규칙을 통해 &quot;&lt;b&gt;안전한&quot; Image&lt;/b&gt;를 제작하자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Image 제작 시 지켜야 할 사항&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;Image 를 제작할 때 &quot;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;신뢰 할 수 없는&lt;/span&gt;&lt;/b&gt;&quot;레지스트리에서 코드를 가져오지 말자.&lt;/li&gt;
&lt;li&gt;또한 &quot;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;취약점이 있는&lt;/span&gt;&lt;/b&gt;&quot; OS Tools 이나 Library를 사용중인 것은 아닌지 확인하자.&lt;/li&gt;
&lt;li&gt;워크로드를 실행하기 위해 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&quot;반드시 필요하지 않은&quot; 의존성(Dependencies)들은 모두 제거&lt;/b&gt;&lt;/span&gt;하자.&lt;/li&gt;
&lt;li&gt;(예를 들어, Base Image로 apline linux를 사용)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Image Scanning&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;취약점이 있는 이미지를 식별하기 위해서 &quot;Image Scanning&quot;을 수행하자.&lt;/li&gt;
&lt;li&gt;Image Scanning 을 수행하는 시점은, CI/CD 파이프라인 과정 내 &lt;u&gt;이미지를 Build 하는 시점&lt;/u&gt;에 함께 수행한다.&lt;/li&gt;
&lt;li&gt;단, 이미지를 빌드 한 이후에도 새로운 취약점이 발견 및 식별 될 수 있으므로 &lt;u&gt;(이미 빌드되어) Registry 내에 존재하는 Image들도 정기적으로 스캐닝을 수행&lt;/u&gt;하자.&lt;/li&gt;
&lt;li&gt;관련해서 &lt;code&gt;Trivy&lt;/code&gt;와 같은 이미지 스캐닝 Tools이 있으니 알아보자.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2 - 컨테이너 실행 시 &lt;code&gt;root&lt;/code&gt; 로 실행하지 않기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 &lt;b&gt;root(UID 0)&lt;/b&gt; 로 Continaer를 실행하게 되면, 해당 Container 를 탈취한 공격자가 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;Privilege Escalation&lt;/b&gt;&lt;/span&gt;을 통해, Container 외부의 Host를 공격 및 탈취 할 수도 있다.&lt;br /&gt;따라서 이미지를 빌드 할 때 &lt;code&gt;USER myapp&lt;/code&gt; 과 같이 명시하여, 반드시 실행 시에는 non-root 유저로 실행하도록 변경해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단, 이미지 빌드 시점에서는 비록 위와 같이 non-root 유저를 사용하도록 지정하였어도,&lt;b&gt; 해당 이미지가 실제 실행되는 시점인&lt;/b&gt; kubernetes 레벨에서 &quot;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;mis-configuration&lt;/b&gt;&lt;/span&gt;&quot;을 통해 &lt;b&gt;overwrite&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;ex. &lt;code&gt;allowPrivilegeEscalation: true&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 이미지 빌드 시점 뿐만 아니라, 실제 &quot;Pod 생성 시점&quot;에도 위와 같은 옵션들을 반드시 &lt;code&gt;false&lt;/code&gt; 처리하고, &lt;code&gt;runAsUser:1000&lt;/code&gt; 처럼 non-root로 실행 되도록 반드시 명시할 필요가 있다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3 - RBAC을 통한 User와 Permission을 관리하자&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RBAC을 통해서 User와 Permission을 관리하되, 가장 중요한 사항은 &lt;b&gt;Privilieges는 최대한 &quot;Restricitve&quot; 하게 제공&lt;/b&gt;하는 것이다. 즉, 정말 필요한 권한만 부여하고 이외의 권한은 주지 않는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;kubernetes's User&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;Kubernetes에서는 &quot;&lt;i&gt;User&lt;/i&gt;&quot;라는 리소스를 별도를 관리하지 않는다.&lt;/li&gt;
&lt;li&gt;Cluster Admin은 &quot;&lt;i&gt;User&lt;/i&gt;&quot;라는 리소스에 대해 여러가지 Authentication 에 대한 전략을 고를 수 있다.&lt;/li&gt;
&lt;li&gt;(ex. Statick Token, Certificate, 3rd Identify Service)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;kubernetes's Service Account&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;kubernetes의 Application user를 나타내며 kubernetes에서 직접 관리하는 리소스이다.&lt;/li&gt;
&lt;li&gt;Service Account의 경우 Token 기반으로 API Server와 Authentication을 진행한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4 - NetworkPolicy를 통한 Pod 간 통신을 제어하자&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본(default)적으로 Cluster 내 모든 Pod 간에는 통신이 자유롭게 가능한 상태이고, 이는 보안상 위험할 수 밖에 없다.&lt;br /&gt;따라서 먼저 Pod들의 모든 Communication을 식별하고, 이후 이들을 제어하기 위해 Cluster 내에 적절한 NetworkPolicy를 구성 및 반영해야 한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt; NetworkPolicy를 구성하기 전에, 가장 중요한 것은 &lt;b&gt;Pod 간에 발생하는 Commuication의 Rules들을 명확히 '식별'&lt;/b&gt;하는 것이다&lt;b&gt;.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;식별 이후 NetworkPolicy를 통해서 트래픽을 제어할 때는, 적용 단위로 IP Address 혹은 Port Level로 제어가 가능하다.&lt;/li&gt;
&lt;li&gt;또한 Network Policy를 구성 할 때는 (마치 RBAC과 동일하게), 대상 Pod에서&lt;b&gt; &quot;필요한 Communication&quot;만 Allowed 처리&lt;/b&gt; 해준다.&lt;/li&gt;
&lt;li&gt;그리고 NetworkPolicy의 실제 구현은, &lt;u&gt;해당 Cluster에 설치된 CNI Plugin에 의해 '구현'된다.&lt;/u&gt;&lt;/li&gt;
&lt;li&gt;만약 NetworkPolicy가 구현되지 않은 CNI를 사용중이라면, (당연하게도) NetworkPolicy를 선언해도 아무런 효과가 없다.&lt;/li&gt;
&lt;li&gt;만약 &quot;Pod&quot; 레벨에서의 통신 제어가 아닌, 한단계 더 상위인 &quot;Service&quot; 레벨에서의 통신을 제어하려면 Istio 와 같은 Service Mesh의 도입을 검토하자.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5 - Communication을 암호화하자&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 Pod 간 통신은 암호화 되지 않은 채로 통신한다. 따라서 공격자에 의해 특정 Pod 등을 탈취 당하게 되면, 공격자가 Pod 간의 통신 내용을 Plain Text 구조 읽을 수 있게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 관련된 Best Practive로 Pod 간 통신을 mTLS 기반으로 암호화 하는 것이다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이를 위해, istio와 같은 Service Mesh 구성을  통해 Pod 통신 간 mTLS를 구현 할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;6 - Secret Data를 안전하게 저장하자&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주로 Secret은 아래와 같이 Sensitive 한 데이터를 보관(store)하는데 사용한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;i&gt;ex. credentials, Secret Tokens, Private Keys, ...&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 Secret을 기본설정으로 사용하게 되면&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt; base64 기반의 인코딩만 이루어지기 때문에&lt;/span&gt;&lt;/b&gt; 안전하지 않다. 예를 들어 공격자가 Secret 리소스 자체에 대해 조회가 가능하면, 안에 보관되어 있는 단순히 인코딩 된 데이터도 조회가 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 Secret 내 Data를 안전하게 보관하기 위한 방법 중&lt;b&gt; 하나로는 kubernetes 자체의 고유한 솔루션&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;&lt;code&gt;EncryptConfiguration&lt;/code&gt; 라는 고유한 리소스를 통해서 암호화 활성화를 하는 것이다.&lt;/li&gt;
&lt;li&gt;단, 이는 암호화 키를 별도로 관리 해야하는 단점이 있다.&lt;/li&gt;
&lt;li&gt;이를 위해 AWS KMS 와 같은 3rd Party의 Key manager 도입이 필요 할 수도 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두번째 방법으로는 &lt;b&gt;3rd Party의 Secret Management solution &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;대표적인 예로 vault 와 같은 3rd-party secret management tool 을 사용해서, Secret 리소스 내 데이터를 보다 안전하게 저장할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;7 - ETCD를 안전하게 보호하자&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;kubernetes의 클러스터 데이터는 모두 &lt;b&gt;ETCD&lt;/b&gt;에 저장된다. 따라서 공격자가 ETCD 접근이 가능하게 되면, API Server 를 우회하는 등을 통해 리소스 강제 업데이트 등의 공격이 가능하다. 사실상 클러스터에 무제한 접근 권한이 탈취되는 것이나 마찬가지 이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 ETCD를 안전하게 보호하기 위해, 아래와 같은 여러가지 보안적 조치를 취해야 한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ETCD는 Cluster 내부에서 실행하지 않고, Cluster 외부에서 실행한다. &lt;u&gt;&lt;i&gt;(External-ETCD)&lt;/i&gt;&lt;/u&gt;&lt;/li&gt;
&lt;li&gt;ETCD의 네트워크에 Firewall 을 세우고, 오직 API Server 만 접근하도록 보호한다.&lt;/li&gt;
&lt;li&gt; ETCD 내 데이터를 암호화 한다 등.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;8 - 백업과 복구를 자동화하자&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ETCD에는 Clutser와 관련된 Manifest 등이 저장되지만, Application들의 Data들은 다른 데이터베이스에 저장된다.&lt;br /&gt;그리고 해당 데이터베이스에는 (애플리케이션에 따라) 신용카드 정보, 의료기록 등 민감한 정보가 있을 수 있기 때문에, 공격자가 읽거나 조작하지 못하도록 이러한 데이터베이스를 안전하게 지켜야만 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 위해 Best Practice 중 하나로, 자동화된 백업과 복구를 사용하는 것이다.&lt;/p&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;그리고 Cluster에 해당 데이터 복구를 쉽게 만든다.&lt;/li&gt;
&lt;li&gt;특히 중요한 점은, &lt;u&gt;백업 데이터 역시 높은 보안수준을 통해서 공격자가 접근 할 수 없도록&lt;/u&gt; 해야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;9 - Security Policies를 구성하자&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Security와 관련된 Best Practices를 숙지하고 항상 Cluster 에 적용해야 하지만, &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;결국 사람에 의한 misconfiguration은 보안 취약점의 가장 큰 이슈이다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 개선하기 위한 Best Practice 중 하나로 &lt;b&gt;Policy as Code&lt;/b&gt; 방식을 통해서 항상 의도된 Policy 들이 반영되는 것을 보장할 수 있도록 하자. (예를 들면, Pod를 root 권한으로 실행하지 않도록 막기 등)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;관련해서는 Third Party 도구들로 &lt;i&gt;Kyverno, Open Policy Agent&lt;/i&gt; 등이 있다.&lt;/li&gt;
&lt;li&gt;이러한 도구를 사용하게 되면, Cluster 내 &quot;Admission Controller&quot; 영역에 도입되면서 구성한 Security Policy 관점에서 Validation을 수행하게 된다.&lt;/li&gt;
&lt;li&gt;이와 같은&lt;b&gt; Automated Validation&lt;/b&gt;을 통해서 Security Polices를 의도대로 항상 유지할 수 있게 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;10 - Disaster Recovery를 도입하자&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; 아무리 잘 막는다고 해도 &lt;u&gt;모든 것을 100% 보호를 보장할 수는 없다.&lt;/u&gt; 특히 보안 특성상 공격자의 경우 정말 단 '하나의 길'만 찾으면 되니깐 절대적으로 유리할 수 밖에 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 &quot;잘 막는다&quot; 라는 관점 이외에도, &lt;u&gt;공격자에 의해 Cluster가 파괴 되었을 때 등을 고려해&lt;/u&gt; &quot;&lt;b&gt;Disatser Recovery&lt;/b&gt;&quot; 관점에서도 적절한 전략이 있어야 한다.&lt;/p&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;이를 위해 Automated 되고, 잘 테스트 된 Recovery Plan을 세운다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Cloud/kubernetes (k8s)</category>
      <category>k8s</category>
      <category>Kubernetes</category>
      <category>security</category>
      <author>aoc55.soft@gmail.com</author>
      <guid isPermaLink="true">https://aoc55.tistory.com/75</guid>
      <comments>https://aoc55.tistory.com/75#entry75comment</comments>
      <pubDate>Thu, 2 Oct 2025 17:22:59 +0900</pubDate>
    </item>
    <item>
      <title>Openstack :: Nova의 Service 목록과 Status &amp;amp; State</title>
      <link>https://aoc55.tistory.com/74</link>
      <description>&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 18px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 100%; text-align: center; height: 18px;&quot;&gt;&lt;span style=&quot;color: #666666; text-align: left; font-family: 'Nanum Gothic';&quot;&gt;개인적으로 공부하는 관점에서 작성한 내용이라, 잘못된 부분이 있을 수 있습니다. 잘못된 부분은 말씀주시면 감사하겠습니다.&lt;/span&gt;&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;500&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cOAuSK/btsQLk7fff6/uVhJbQ99XZ5yXWK39Xl8H1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cOAuSK/btsQLk7fff6/uVhJbQ99XZ5yXWK39Xl8H1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cOAuSK/btsQLk7fff6/uVhJbQ99XZ5yXWK39Xl8H1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcOAuSK%2FbtsQLk7fff6%2FuVhJbQ99XZ5yXWK39Xl8H1%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;600&quot; height=&quot;500&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;500&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;div class=&quot;markdown-body&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Openstack CLI로 &lt;code&gt;openstack compute service list&lt;/code&gt; 라고 입력 시 보통 아래와 출력이 되는데 관련해서 조금 알아보자.&lt;/p&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;2102&quot; data-origin-height=&quot;344&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RkC9L/btsQIAw7OXM/8sYQ5irjKUFcBlxEIsaQvk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RkC9L/btsQIAw7OXM/8sYQ5irjKUFcBlxEIsaQvk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RkC9L/btsQIAw7OXM/8sYQ5irjKUFcBlxEIsaQvk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRkC9L%2FbtsQIAw7OXM%2F8sYQ5irjKUFcBlxEIsaQvk%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;994&quot; height=&quot;163&quot; data-origin-width=&quot;2102&quot; data-origin-height=&quot;344&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여기서 &lt;code&gt;gc6-compt1&lt;/code&gt;, &lt;code&gt;gc6-compt2&lt;/code&gt; 는 Openstack 설치 시 Compute Node의 역할을 하는 Node의 Host 이름이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Nova의 Service 목록&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 보았듯이 &lt;code&gt;openstack compute service list&lt;/code&gt; 로 입력 시 출력되는 Nova의 Service 들을 간단히 알아보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;nova-compute&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;실제 VM을 하이퍼바이저 위에서 생성 및 관리등을 하는 워커 프로세스.&lt;/li&gt;
&lt;li&gt;ex. KVM/Libvirt API를 호출해서 VM을 띄우고, attach/detach, 스냅샷, 콘솔 등등을 처리.&lt;/li&gt;
&lt;li&gt;스케줄러가 결정한 요청을 받아서 실행함.&lt;/li&gt;
&lt;li&gt;서비스 배치의 경우 Compute Node 마다 실행.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;nova-scheduler&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;어느 nova-compute에 VM 올릴지 스케줄링을 담당한다.&lt;/li&gt;
&lt;li&gt;스케줄링 과정에서 요청의 Flavor, AZ, .. 등을 고려해 여러 필터 등을 거쳐서 최종적으로 배치될 nova-compute(compute node)의 위치를 결정한다.&lt;/li&gt;
&lt;li&gt;스케줄러 인스턴스의 경우 여러 개의 스케줄러를 띄울 수 있고, 각 스케줄러는 독립적으로 병렬적으로 스케줄링을 할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;nova-conductor&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;nova-compute 프로세스와 실제 Nova가 사용하는 DB 간의 중개 역할을 한다.&lt;/li&gt;
&lt;li&gt;즉, 각 Compute Node(만약수천개라면?)에 뜬 서비스들이 각각 개별적으로 DB 연결을 하는 것이 아니라, &lt;b&gt;DB 연결에 대해 중앙 제어화&lt;/b&gt; 하기 위한 목적이다.&lt;/li&gt;
&lt;li&gt;만약 nova-compute 프로세스가 모두 '각자' 연결하면? (예전에는 이랬다고 한다) 커넥션 증가, 보안 취약, 충돌/락 문제 등등... 의 문제가 발생.&lt;/li&gt;
&lt;li&gt;따라서 nova-compute 프로세스가 DB에 직접적으로 Write 등을 하는게 아니라, nova-conductor에&lt;b&gt; RPC 콜 방식&lt;/b&gt;으로 중개를 요청한 뒤, &lt;b&gt;요청을 받은 nova-conductor에서&lt;/b&gt; 실질적으로 DB 연결 및 Write/Read 등을 수행한다.&lt;/li&gt;
&lt;li&gt;nova-conductor의 배치의 경우, &quot;Stateless&quot;기반이기 떄문에 여러 개의 프로세스를 동시에 구동하는데 문제가 없다.&lt;/li&gt;
&lt;li&gt;(보통 컨트롤러 노드 2~3대 이상이면, 확장성을 위해서 nova-conductor 역시 각 노드에 배포하는 식으로 권고한다고 한다)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;excel&quot;&gt;&lt;code&gt;nova-compute (각 노드)
     │ RPC
     ▼
nova-conductor (컨트롤러)
     │ SQLAlchemy/DB Driver
     ▼
Nova DB&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;nova-api-osapi&lt;/b&gt;, &lt;b&gt;nova-api-metadata &lt;/b&gt;가 있는데 이들의 경우에는 &quot;compute service&quot; 보다는 &lt;b&gt;API Server 프로세스&lt;/b&gt; 이기에, &lt;code&gt;openstack compute service list&lt;/code&gt;에는 조회되지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;관련해서 실제로 아래와 같이 Nova가 사용하는 Database 내 &lt;code&gt;servies&lt;/code&gt; 라는 테이블을 조회하면 아래와 같다.&lt;/p&gt;
&lt;pre class=&quot;n1ql&quot;&gt;&lt;code&gt;mysql&amp;gt; select host, `binary`, `topic` from nova.services;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;gherkin&quot;&gt;&lt;code&gt;+-----------------------------------+--------------------+-----------+
| host                              | binary             | topic     |
+-----------------------------------+--------------------+-----------+
| nova-api-osapi-c6465df8f-wnsgp    | nova-osapi_compute | NULL      |
| nova-conductor-6df5cb68d8-phzqs   | nova-conductor     | conductor |
| nova-scheduler-f47d4dcb-jz88m     | nova-scheduler     | scheduler |
| nova-api-metadata-ff749945c-9zlh4 | nova-metadata      | NULL      |
| gc6-compt2                        | nova-compute       | compute   |
| gc6-compt1                        | nova-compute       | compute   |
| nova-scheduler-f47d4dcb-qwtj9     | nova-scheduler     | scheduler |
| nova-api-metadata-ff749945c-mvlnw | nova-metadata      | NULL      |
| nova-api-metadata-ff749945c-kj54c | nova-metadata      | NULL      |
| nova-api-osapi-c6465df8f-k8v8b    | nova-osapi_compute | NULL      |
| nova-api-metadata-ff749945c-5585d | nova-metadata      | NULL      |
| nova-scheduler-f47d4dcb-55mbf     | nova-scheduler     | scheduler |
| nova-conductor-6df5cb68d8-n6l6v   | nova-conductor     | conductor |
| nova-scheduler-f47d4dcb-bl79h     | nova-scheduler     | scheduler |
+-----------------------------------+--------------------+-----------+&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;nova-api-osapi-..&lt;/code&gt;, &lt;code&gt;nova-api-metadata-...&lt;/code&gt; 관련 Row들은 &lt;code&gt;topic&lt;/code&gt; Column이 NULL 인 것을 알 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 사실상 &lt;code&gt;openstack compute service list&lt;/code&gt; 에서는 &lt;code&gt;topic&lt;/code&gt; 필드의 &lt;code&gt;NULL&lt;/code&gt; 이 아닌 서비스만 출력해준다.&lt;/p&gt;
&lt;h1&gt;State &amp;amp; Status&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Nova의 Service 관련하여 조회 할 경우, 아래와 같이 상태 필드로 &lt;b&gt;State&lt;/b&gt; 와 &lt;b&gt;Status&lt;/b&gt; 가 있다.&lt;/p&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;2122&quot; data-origin-height=&quot;352&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c5ZRYM/btsQILZzbig/DHUpszb3KK3jsPxxwLpcO1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c5ZRYM/btsQILZzbig/DHUpszb3KK3jsPxxwLpcO1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c5ZRYM/btsQILZzbig/DHUpszb3KK3jsPxxwLpcO1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc5ZRYM%2FbtsQILZzbig%2FDHUpszb3KK3jsPxxwLpcO1%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;2122&quot; height=&quot;352&quot; data-origin-width=&quot;2122&quot; data-origin-height=&quot;352&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;관련해서 무엇을 의미하는지 간단히 알아보자.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;State&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;State&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;해당 필드로 올 수 있는 값(value)으로는 &lt;code&gt;up&lt;/code&gt;, &lt;code&gt;down&lt;/code&gt; 이다.&lt;/li&gt;
&lt;li&gt;순수하게, 해당 서비스가 살아있는지 여부에 대한 확인 목적이다.&lt;/li&gt;
&lt;li&gt;별도의 관리자 등이 명령어로 제어할 일 없고, 각 서비스들이 스스로 Heart Beat 를 보내는 방식으로 갱신하는 영역이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Down 테스트&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;특정 Compute Node 에서 일부로 &lt;code&gt;nova-compute&lt;/code&gt; Process를 내려본 뒤 관찰하기.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;coq&quot;&gt;&lt;code&gt;| bf18e82c-a0fe-4ecb-aa74-e1b5eff303f4 | nova-compute   | gc6-compt2                      | az1      | enabled | down  | 2025-09-22T13:59:16.000000 |&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;State가 &lt;code&gt;down&lt;/code&gt; 으로 관측된다. (단, Status는 그대로 &lt;code&gt;enabled&lt;/code&gt; 임)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;각 서비스들의 Heart Beat 기록 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면, State 의&lt;code&gt;up&lt;/code&gt; &amp;amp; &lt;code&gt;down&lt;/code&gt; 을 판별하기 위해서 사용되는 &quot;heart beat&quot; 는 어떤식으로 이루어지는 것일까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보통 각 서비스들이 프로세스 내 주기적 Task를 통해서, &lt;b&gt;스스로&lt;/b&gt; (nova-conductor 를 거쳐) &lt;b&gt;Nova의 Services DB 내 직접 레코드를 기록하는 방식&lt;/b&gt;이라고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;관련해서 역시 &lt;code&gt;nova.services&lt;/code&gt; Table 을 조회하면 아래와 관련된 필드를 찾을 수 있다.&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;select * form nova.services;&lt;/code&gt;&lt;/pre&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3956&quot; data-origin-height=&quot;618&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/G8ZBh/btsQH8HvMSy/cGiS2PJnZxnnM1NwcdUzkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/G8ZBh/btsQH8HvMSy/cGiS2PJnZxnnM1NwcdUzkK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/G8ZBh/btsQH8HvMSy/cGiS2PJnZxnnM1NwcdUzkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FG8ZBh%2FbtsQH8HvMSy%2FcGiS2PJnZxnnM1NwcdUzkK%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;3956&quot; height=&quot;618&quot; data-origin-width=&quot;3956&quot; data-origin-height=&quot;618&quot;/&gt;&lt;/span&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;테이블 출력에서 아래와 같이 관련된 &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;&lt;code&gt;last_seen_up&lt;/code&gt; : 마지막에 각 서비스들이 '스스로 살아있음'을 보낸 시각.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;report_count&lt;/code&gt; : 하트비트를 보고한 횟수&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 필드들 기반에서 Openstack CLI에서는 위의 &lt;code&gt;last_seen_up&lt;/code&gt; 시간과 &lt;code&gt;updated_at&lt;/code&gt; 시간을 비교해서, 해당 서비스가 &lt;code&gt;up&lt;/code&gt; 인지 &lt;code&gt;down&lt;/code&gt; 인지 판별하는 방식이라고 한다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Status&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 Status 를 알아보자. (State 아님)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Status&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;해당 필드로 올 수 있는 값(value)으로는 &lt;code&gt;enabled&lt;/code&gt;, &lt;code&gt;diasbled&lt;/code&gt; 이 있다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;ex.&lt;/b&gt; &quot;nova-compute&quot;의 경우 오픈스택 관리자가 해당 노드에 VM 스케줄링 할지 여부에 대한 결정으로, 만약&lt;code&gt;disabled&lt;/code&gt; 인 경우에는 새로운 VM 생성 등이 스케줄링 되지 않는다.&lt;/li&gt;
&lt;li&gt;이 속성의 경우, 실제 필요에 따라 명령어로 제어할 일이 &lt;b&gt;충분히 발생&lt;/b&gt;한다. (위와 같이 VM 신규 생성을 막거나 할때 등)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Status 제어 CLI (ex. nova-compute)&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;# enable
openstack compute service set --enable gc6-compt1 nova-compute

# disable
openstack compute service set --disable gc6-compt1 nova-compute
# | gc6-compt1                      | az1      | disabled |&lt;/code&gt;&lt;/pre&gt;
&lt;/div&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;</description>
      <category>Cloud/Openstack</category>
      <category>cloud</category>
      <category>CloudNative</category>
      <category>IaaS</category>
      <category>Nova</category>
      <category>openstack</category>
      <author>aoc55.soft@gmail.com</author>
      <guid isPermaLink="true">https://aoc55.tistory.com/74</guid>
      <comments>https://aoc55.tistory.com/74#entry74comment</comments>
      <pubDate>Tue, 23 Sep 2025 00:06:10 +0900</pubDate>
    </item>
    <item>
      <title>k8s :: kata container (v3) 설치 해보기 with k8s - #2</title>
      <link>https://aoc55.tistory.com/73</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class=&quot;markdown-body&quot;&gt;
&lt;h1&gt;#2 :: kubernetes 와 kata 연동하기&lt;br /&gt;&lt;br /&gt;&lt;/h1&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;280&quot; data-origin-height=&quot;280&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/drj1hl/btsPVE1wYTz/MxVcu4qRoZjHcRsn2NihEk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/drj1hl/btsPVE1wYTz/MxVcu4qRoZjHcRsn2NihEk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/drj1hl/btsPVE1wYTz/MxVcu4qRoZjHcRsn2NihEk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdrj1hl%2FbtsPVE1wYTz%2FMxVcu4qRoZjHcRsn2NihEk%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;280&quot; height=&quot;280&quot; data-origin-width=&quot;280&quot; data-origin-height=&quot;280&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot;&gt;이전 편에서 kata runtime과 containerd 를 설치해서 직접 kata 기반의 &lt;b&gt;Container&lt;/b&gt;를 만들어 보았고, &lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot;&gt;이제 &lt;b&gt;kubernetes&lt;/b&gt; 레벨에서 kata 기반의 &lt;b&gt;Pod&lt;/b&gt;를 만들어본다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;이전편&lt;/b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;gt;&amp;gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;https://aoc55.tistory.com/72&quot;&gt;https://aoc55.tistory.com/72&lt;/a&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;2-0 :: 목표 및 실습 환경&lt;/h2&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;앞에서까지, &lt;code&gt;containerd&lt;/code&gt; 를 통해서 &lt;code&gt;kata&lt;/code&gt;를 기반 Container 직접 생성했다면,&lt;/li&gt;
&lt;li&gt;이제는 한단계 더 나아가 Container Orchestrator 인 kubernetes 를 통해서 &lt;b&gt;&lt;span style=&quot;color: #1b711d;&quot;&gt;kata 기반의 Pod 생성&lt;/span&gt;&lt;/b&gt;하기 목표&lt;b&gt;.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&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;kubernetes의 Control Plane을 통해서 =&amp;gt; Pod 생성 요청&lt;/li&gt;
&lt;li&gt;이후 스케줄러의 Pod가 생성될 Worker Node가 선정되면, 이후 해당 Worker Node에서 아래와 같이 흐른다.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;KakaoTalk_Photo_2025-08-26-08-28-23.png&quot; data-origin-width=&quot;2288&quot; data-origin-height=&quot;736&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cCAqba/btsP4TKCpYo/okWBcOkPaGXIry0sToHti1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cCAqba/btsP4TKCpYo/okWBcOkPaGXIry0sToHti1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cCAqba/btsP4TKCpYo/okWBcOkPaGXIry0sToHti1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcCAqba%2FbtsP4TKCpYo%2FokWBcOkPaGXIry0sToHti1%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;2288&quot; height=&quot;736&quot; data-filename=&quot;KakaoTalk_Photo_2025-08-26-08-28-23.png&quot; data-origin-width=&quot;2288&quot; data-origin-height=&quot;736&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이를 위해 대략 다음과 같이 진행한다.&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;kubespray 통해 Control Plane으로만 구성된 k8s Cluster 를 우선 생성한다.&lt;/li&gt;
&lt;li&gt;그리고 이전 과정에서 kata-runtime 을 설치한 Ubuntu Host를 k8s의 Worker Node로 직접 join 한다.&lt;/li&gt;
&lt;li&gt;이후 kubernetes 통해서, 해당 Worker Node 위에서 &lt;b&gt;&lt;span style=&quot;color: #1b711d;&quot;&gt;kata 기반의 Pod&lt;/span&gt;&lt;/b&gt;가 정상 생성 되는지 확인한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2-1 :: kubespray 통한 k8s Cluster 생성&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;신규 kubernetes Cluster 구성을 위해서 kubespray를 활용한다. &lt;i&gt;(물론 꼭 kubespary 뿐만 아니라, kubeadm 통한 직접 설치 방식 등도 가능하다!)&lt;/i&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;kubespary 준비&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 git 으로 kubespary 코드를 clone.&lt;br /&gt;이후 안정적인 설치를 위해 kubespary의 release 버전으로 설치를 위해 &lt;code&gt;checkout&lt;/code&gt; 을 수행.&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;git clone https://github.com/kubernetes-sigs/kubespray.git kubespary
cd kubespary
git checkout v2.27.1&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;inventory 파일 작성&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;k8s Cluster 설치를 위한 ansible 기반의 inventory 파일을 작성.&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;# 미리 정의된 샘플 인벤토리를 복사
cp -r inventory/sample/ inventory/kata-cluster&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;# vim kubespary/inventory/kata-cluster/inventory.ini 

[kube_control_plane]
k8s-control1    ansible_host=172.16.30.11
k8s-control2    ansible_host=172.16.30.12
k8s-control3    ansible_host=172.16.30.13

[etcd:children]
kube_control_plane

[kube_node]
# kata-worker1     ansible_host=172.16.30.31&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;단, worker node(kata-worker1)의 경우 아래에서 kubeadm 통해서 수동으로 설치 및 join 할 예정이기에 해당 kubespary inventory 내에서는 주석처리한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;k8s cluster 주요 변수 설정&lt;/h3&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;kubespary/inventory/kata-cluster/...&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;위 디렉터리 하위에 있는 여러 yaml 파일 내, Cluster 구성을 위한 중요 Cluster 변수들을 세팅을 &quot;필요에 따라&quot; 설정한다.&lt;/li&gt;
&lt;li&gt;자세한 내용은 &lt;a href=&quot;https://github.com/kubernetes-sigs/kubespray?tab=readme-ov-file&quot;&gt;GitHub - kubernetes-sigs/kubespray: Deploy a Production Ready Kubernetes Cluster&lt;/a&gt; 참조&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex. Cluster 구성 시, kubespary 통해서 CNI는 설치하지 않을 예정이라 &quot;비활성화&quot; 설정.&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;# vim kubespary/inventory/kata-cluster/group_vars/k8s_cluster/k8s-cluster.yml

# ...
kube_network_plugin: none
# ...&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;아래에 별도로 따로 CNI 설치 할 예정.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;k8s cluster 구성을 위한 playbook 수행&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(ansible) playbook 수행을 위해 가상환경(venv)를 만들고 필요 패키지를 설치한다.&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;cd kubespary/

# venv 생성
python3 -m venv .venv
source .venv/bin/activate

# 사전 의존 패키지 설치
pip3 install -r requirements.txt&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 Cluster 구성을 위한 &quot;&lt;span style=&quot;color: #1b711d;&quot;&gt;cluster&lt;/span&gt;&quot; Playbook 수행&lt;/p&gt;
&lt;pre class=&quot;mel&quot;&gt;&lt;code&gt;# cluster playbook 수행
ansible-playbook -i inventory/kata-cluster/inventory.ini --become cluster.yml &lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;생성한 k8s cluster의 kube-config 추출&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;playbook 이 성공적으로 끝났다면 Cluster 구성이 완료된 것이다. &lt;i&gt;(CNI 설치 제외)&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;직전에 Cluster 구성을 위한 Playbook을 control node &quot;내&quot;에서가 아닌, 별도의 &lt;u&gt;&lt;i&gt;deploy node&lt;/i&gt;&lt;/u&gt;에서 수행함.&lt;br /&gt;따라서 &lt;u&gt;&lt;i&gt;deploy node&lt;/i&gt;&lt;/u&gt;에서 Cluster에 접근 (ex. &lt;code&gt;kubectl...&lt;/code&gt;) 하기 위해, control node 1번 내 &lt;code&gt;kubeconfig&lt;/code&gt; 를 추출한다.&lt;br /&gt;(만약 playbook을 control node '내'에서 직접 수행 하였을 경우에는 불필요)&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;rsync -e &quot;ssh&quot; \
      --rsync-path=&quot;sudo rsync&quot; \
      -avz root@172.16.30.11:/root/.kube/config &quot;${HOME}/.kube/config&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;nginx&quot;&gt;&lt;code&gt;sed -i 's@server.*@server: https://172.16.30.11:6443@g' &quot;${HOME}/.kube/config&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 &lt;u&gt;&lt;i&gt;deploy node &lt;/i&gt;&lt;/u&gt;에서 &lt;code&gt;kubectl get nodes&lt;/code&gt; 를 통해 정상적으로 k8s Cluster와 통신이 되는지 확인.&lt;/p&gt;
&lt;pre class=&quot;lsl&quot;&gt;&lt;code&gt;kubectl get node
# ---
NAME           STATUS     ROLES           AGE   VERSION
k8s-control1   NotReady   control-plane   19m   v1.31.9
k8s-control2   NotReady   control-plane   18m   v1.31.9
k8s-control3   NotReady   control-plane   18m   v1.31.9&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CNI를 설치하기 이전임으로, &lt;code&gt;STATUS&lt;/code&gt;는 NotReady 상태&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2-2 :: CNI (kube-ovn) 설치&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만든 kubernetes Cluster 의 CNI를 구성하기 위해, &lt;code&gt;kube-ovn&lt;/code&gt; 을 설치.&lt;br /&gt;(CNI로&lt;code&gt;kube-ovn&lt;/code&gt;을 사용하는 이유는 해당 주제와는 무관한 다른 모종의 이유로 선정한 것으로, 아마도 다른 CNI를 사용해도 무관할 듯하다.)&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;kube-ovn 설치 스크립트 다운로드&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;kube-ovn 의 경우 helm을 통해 정식으로 설치할 수 있으나, 이번 실습에서 빠른 &amp;amp; 간단 설치를 위해 제공되는 &quot;스크립트&quot;로 한번에 설치함.&lt;/p&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;wget https://raw.githubusercontent.com/kubeovn/kube-ovn/refs/tags/v1.14.5/dist/images/install.sh &lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;kube-ovn 1.14.5&lt;/code&gt; 설치 스크립트 다운로드&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(필요 시) script 내 주요부분 수정&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;# vim install.sh 

# ...
POD_CIDR=&quot;10.16.0.0/16&quot; # Do NOT overlap with NODE/SVC/JOIN CIDR
POD_GATEWAY=&quot;10.16.0.1&quot;
SVC_CIDR=&quot;10.96.0.0/12&quot; # Do NOT overlap with NODE/POD/JOIN CIDR
JOIN_CIDR=&quot;100.64.0.0/16&quot; # Do NOT overlap with NODE/POD/SVC CIDR
# ...&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ex. Pod, Cluster IP 등의 대역을 확인 및 설정가능.&lt;/li&gt;
&lt;li&gt;만약 별도의 이유가 없으면, 초기값 그대로 두고 진행.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;kube-ovn 설치 및 확인&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 다운로드 받은 설치 스크립트로 kube-ovn 설치.&lt;/p&gt;
&lt;pre class=&quot;mipsasm&quot;&gt;&lt;code&gt; bash install.sh &lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CNI 설치가 정상적으로 끝났는지 확인하자.&lt;/p&gt;
&lt;pre class=&quot;lsl&quot;&gt;&lt;code&gt;kubectl get nodes
# ---
NAME           STATUS   ROLES           AGE   VERSION
k8s-control1   Ready    control-plane   21m   v1.31.9
k8s-control2   Ready    control-plane   21m   v1.31.9
k8s-control3   Ready    control-plane   21m   v1.31.9&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이제 각 Node의 Status가 &lt;code&gt;Ready&lt;/code&gt; 상태가 됨.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기까지 수행함으로서 본격적으로 kata Container를 실행하기 위한, &lt;span style=&quot;color: #1b711d;&quot;&gt;&lt;b&gt;사전 k8s cluster 구성완료.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2-3 :: kata container 기반의 k8s Worker Node로 수동 구성&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전 과정에서 진행한 kata runtime이 설치된 Ubuntu Host를 =&amp;gt; &amp;nbsp;k8s cluster에 &quot;worker node&quot;로 추가.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Node 사전설정&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Worker Node로 Join 작업을 진행하기 전에, 필요한 OS 설정 등을 진행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 추가적인 커널 파라미터 세팅 등이 반드시 이루어져하나, 이번 실습 목적 자체가 kata Pod가 생성이 가능한지만 보는 것이기에 &quot;최대한 간단하게&quot; 수행.&lt;/p&gt;
&lt;pre class=&quot;gauss&quot;&gt;&lt;code&gt;cat &amp;lt;&amp;lt;EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables=1
net.ipv4.ip_forward = 1
EOF

sudo sysctl --system # 즉시 적용&lt;/code&gt;&lt;/pre&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;pre class=&quot;stylus&quot;&gt;&lt;code&gt;sudo swapoff -a &amp;amp;&amp;amp; sudo sed -i '/swap/s/^/#/' /etc/fstab&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;swap off 해제&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;sudo apt-get update
sudo apt-get install -y ipvsadm&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;ruby&quot;&gt;&lt;code&gt;cat &amp;lt;&amp;lt;EOF | sudo tee /etc/modules-load.d/ipvs.conf
br_netfilter
ip_vs
ip_vs_rr
ip_vs_wrr
ip_vs_sh
nf_conntrack
overlay
EOF&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;sudo modprobe br_netfilter
sudo modprobe ip_vs
sudo modprobe ip_vs_rr
sudo modprobe ip_vs_wrr
sudo modprobe ip_vs_sh
sudo modprobe nf_conntrack
sudo modprobe overlay&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;kube-proxy의 backend로 ipvs 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;kubelet, kubeadm, kubectl 설치&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 Node의 경우에는, 별도로 kubespary를 쓰지 않고 &lt;b&gt;kubeadm&lt;/b&gt; 방식으로 join을 직접 진행한다.&lt;/p&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;apt update
apt install -y apt-transport-https ca-certificates curl gpg

# k8s 패키지 keyring 저장
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.31/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg

# k8s 패키지 저장소 등록
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.31/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list

# 설치 진행
apt update
apt install -y kubelet kubeadm kubectl
apt-mark hold kubelet kubeadm kubectl&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 kubelet 을 활성화 해준다.&lt;/p&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;systemctl enable kubelet.service
systemctl start kubelet.service&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;runc 추가 설치&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞서, 작업 대상 host에서 Containerd의 runtime 으로 &lt;code&gt;kata&lt;/code&gt; 만 설치 및 기본 Runtime 으로 설정함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 현재 k8s Cluster에 구성된 CNI인 &lt;code&gt;kube-ovn&lt;/code&gt; 의 경우, daemonset 기반으로 CNI 구성을 위한 Pod를 생성한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때, 해당 Pod 역시 &lt;code&gt;kata&lt;/code&gt; Runtime 기반으로 실행할 경우 &lt;code&gt;hostpath&lt;/code&gt; 관련 오류 발생하면서 기동되지 않음.&lt;br /&gt;물론 이와 관련해서 자세히 보면 해결할 방법이 있을 수 있으나, 금번 실습 목적에 맞게 우선 아래와 같이 &lt;b&gt;runc를 추가로 설치.&lt;/b&gt;&lt;br /&gt;(겸사겸사 한 worker node에서 2개의 runtime 이 모두 존재할 수 있는지도 확인!)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 설치 이후에는 이를 Containerd 내에서 runc를 기본 Runtime으로 다시 바꿔주자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 사항이 반영된 그림으로 보면 아래와 같다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2884&quot; data-origin-height=&quot;1176&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MfgG7/btsP6egefvH/BRdCgaC6DQXlvGokpC2R30/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MfgG7/btsP6egefvH/BRdCgaC6DQXlvGokpC2R30/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MfgG7/btsP6egefvH/BRdCgaC6DQXlvGokpC2R30/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMfgG7%2FbtsP6egefvH%2FBRdCgaC6DQXlvGokpC2R30%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;2884&quot; height=&quot;1176&quot; data-origin-width=&quot;2884&quot; data-origin-height=&quot;1176&quot;/&gt;&lt;/span&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;runc 설치&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;wget https://github.com/opencontainers/runc/releases/download/v1.3.0/runc.amd64
install -m 755 runc.amd64 /usr/local/sbin/runc&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;containerd 내 runc 설정&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;runc 설치 이후, worker node 내에서 &lt;code&gt;runc&lt;/code&gt;, &lt;code&gt;kata&lt;/code&gt; Runtime 방식 모두 지원가능 하도록 추가 설정을 진행.&lt;br /&gt;(사실 runc 관련 설정은 기본적으로 containerd 설정에 반영되어 있으므로, default runtime만 runc로 다시 설정)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;containerd 설정&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;# vim /etc/containerd/config.toml
[plugins]

    [plugins.&quot;io.containerd.grpc.v1.cri&quot;]

        [plugins.&quot;io.containerd.grpc.v1.cri&quot;.containerd]
            # default_runtime_name = &quot;kata&quot;
            default_runtime_name = &quot;runc&quot;
             [plugins.&quot;io.containerd.grpc.v1.cri&quot;.containerd.runtimes]
                 [plugins.&quot;io.containerd.grpc.v1.cri&quot;.containerd.runtimes.runc]
                [plugins.&quot;io.containerd.grpc.v1.cri&quot;.containerd.runtimes.runc.options]
       SystemdCgroup = true&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;default runtime을 다시 &lt;code&gt;runc&lt;/code&gt; 로 바꾸어 주었다.&lt;/li&gt;
&lt;li&gt;그리고 &lt;code&gt;runc&lt;/code&gt; 에서 &lt;code&gt;SystemdCgroup&lt;/code&gt; 활성화.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Containerd 재기동&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;systemctl daemon-reload
systemctl restart containerd&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;확인 &lt;code&gt;systemctl status containerd&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Worker Node Join&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 해당 Host를, 구성한 k8s cluster 내에 worker node로 join 하자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Control Node에서 Join을 위한 token 발행&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;gauss&quot;&gt;&lt;code&gt;# Control node 에서 수행
kubeadm token create --print-join-command

# 출력 예시
kubeadm join 127.0.0.1:6443 --token qls8g6.t83c55c95yptlkvh --discovery-token-ca-cert-hash sha256:a06d648473860b2962e99c79d065b306b97b15b0a4447129dd9609afd9012d4f&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;출력에서 &lt;code&gt;127.0.0.1&lt;/code&gt; 부분은 이후 수행 시 실제 Control Node의 IP로 변경해서 수행한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Worker Node Join 수행&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;# Worker Node로 추가할 Host에서 수행
# Control Node의 IP로 변경해서 사용
kubeadm join 172.16.30.11:6443 --token qls8g6.t83c55c95yptlkvh --discovery-token-ca-cert-hash sha256:a06d648473860b2962e99c79d065b306b97b15b0a4447129dd9609afd9012d4f &lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;복사한 명령어를 Join 을 진행할 실제 Host에서 수행한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(만약) 중간에 인증서 위치가 안 맞아서 join 이 안되는 경우 '임시'로 아래와 심볼릭 링크를 설정해준다.&lt;/p&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;mkdir /etc/kubernetes/ssl/
ln -s /etc/kubernetes/pki/ca.crt /etc/kubernetes/ssl/ca.crt&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Worker Node Join - 확인&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정상적으로 Join 이 진행되었다면, 이후 CNI를 위한 Pod들이 자동으로 올라오면서 CNI 구성까지 진행된다.&lt;br /&gt;이후 모든 요소들이 올라오면 아래와 같이 Node의 상태가 &lt;code&gt;Ready&lt;/code&gt; 상태인지 확인한다.&lt;/p&gt;
&lt;pre class=&quot;lsl&quot;&gt;&lt;code&gt;kubectl get nodes

# -----
NAME           STATUS   ROLES           AGE   VERSION
k8s-control1   Ready    control-plane   34m   v1.31.9
k8s-control2   Ready    control-plane   34m   v1.31.9
k8s-control3   Ready    control-plane   34m   v1.31.9
kata-worker1   Ready    &amp;lt;none&amp;gt;          82s   v1.31.12. # ---&amp;gt; 신규 추가&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2-4 :: kata 기반의 Pod 생성해보기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;k8s Cluster에 Join 까지 완료하였으니, 이제 kubernetes를 통해 kata 기반의 Pod를 생성해보자.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;kata 전용 Runtime Class 선언&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;kubenetetes 에서 Pod 생성 시, 사용할 runtime을 지정하기 위한 (kata) &lt;code&gt;RuntimeClass&lt;/code&gt; 를 선언.&lt;/p&gt;
&lt;pre class=&quot;dts&quot;&gt;&lt;code&gt;apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
  name: kata
handler: kata&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이후 &lt;code&gt;kubectl apply -f ...&lt;/code&gt; 로 선언한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;kata 기반 Pod 생성하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 정말 Pod를 생성하자. 단 생성 시에 아래와 같이 &lt;code&gt;runtimeClassName&lt;/code&gt; 을 지정한다.&lt;/p&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;apiVersion: v1
kind: Pod
metadata:
  name: nginx-kata
spec:
  nodeName: kata-worker1  # 신규 추가한 Node
  runtimeClassName: kata  # kata 지정
  containers:
  - name: nginx
    image: nginx&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이후 &lt;code&gt;kubectl apply -f ...&lt;/code&gt; 로 선언한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Pod 생성 확인&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래와 같이 kata container 기반의 Pod가 정상 생성 되었음을 확인.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;kubectl get pods -o wide

# ---
NAME         READY   STATUS    RESTARTS   AGE    IP          NODE           NOMINATED NODE   READINESS GATES
nginx-kata   1/1     Running   0          3m9s   10.16.0.9   kata-worker1   &amp;lt;none&amp;gt;           &amp;lt;none&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 Worker Node(Host) 관점에서 &lt;b&gt;&lt;span style=&quot;color: #1b711d;&quot;&gt;Process&lt;/span&gt;&lt;/b&gt; 레벨로 확인하자.&lt;/p&gt;
&lt;pre class=&quot;dos&quot;&gt;&lt;code&gt;ps aux&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;kata-worker1&lt;/code&gt; Node에서 수행&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;root       65638  3.2  0.2  70752 24064 ?        Sl   23:52   0:00 /usr/local/bin/containerd-shim-kata-v2 -id 6e977248867557095fb99892294ac1c4580e06e635dc3baca6df97f085927677 -namespace k8s.io -address /run/containerd/containerd.sock -publish-binary /usr/local/bin/containerd
root       65651  0.0  0.0 2306624 4224 ?        Sl   23:52   0:00 /usr/libexec/virtiofsd --socket-path virtiofsd.sock --shared-dir /run/kata-containers/shared/sandboxes/6e977248867557095fb99892294ac1c4580e06e635dc3baca6df97f085927677/ro --cache auto --sandbox none --seccomp none --thread-pool-size=1 -o announce_submounts
root       65654 97.4  2.1 2941140 170188 ?      Sl   23:52   0:01 /usr/bin/qemu-system-x86_64 -name sandbox-6e977248867557095fb99892294ac1c4580e06e635dc3baca6df97f085927677 -kernel /usr/share/kata-containers/vmlinux.container -append reboot=k panic=1 systemd.unit=kata-containers.target systemd.mask=systemd-networkd.service root=/dev/pmem0p1 rootflags=dax,data=ordered,errors=remount-ro ro rootfstype=ext4 cgroup_no_v1=all systemd.unified_cgroup_hierarchy=1 selinux=0 -&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;kata 기반으로 실행되었기에, &lt;code&gt;contained-shim-kata-v2&lt;/code&gt;, &lt;code&gt;viriofsd&lt;/code&gt;, &lt;code&gt;qemu-..&lt;/code&gt; 3개의 프로세스가 Host에서 실행된 것을 확인.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;b&gt;즉, kubernetes Level에서, kata 기반의 Pod 생성을 완료하였다!&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;(+) runc 기반 Pod 도 생성해보기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;혹시 모르니, &lt;code&gt;runc&lt;/code&gt; 기반으로도 Pod를 생성해본다.&lt;/p&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;apiVersion: v1
kind: Pod
metadata:
  name: nginx-runc
spec:
  nodeName: kata-worker1  # 신규 추가한 Node
  # 별도 runtimeClass 미지정
  containers:
  - name: nginx
    image: nginx&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;default가 &lt;code&gt;runc&lt;/code&gt; 기반임으로, 별도의 runtimeClass는 지정하지 않음.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;kubectl get pods -o wide

# ---
NAME         READY   STATUS    RESTARTS   AGE    IP           NODE           NOMINATED NODE   READINESS GATES
nginx-kata   1/1     Running   0          3m3s   10.16.0.10   kata-worker1   &amp;lt;none&amp;gt;           &amp;lt;none&amp;gt;
nginx-runc   1/1     Running   0          30s    10.16.0.11   kata-worker1   &amp;lt;none&amp;gt;           &amp;lt;none&amp;gt;&lt;/code&gt;&lt;/pre&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;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;b&gt;이를 통해 하나의 worker node(containerd) 에서, runc와 kata runtime 이 각각 존재할 수 있음을 확인할 수 있다.&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;역시 실제 Host 에서 Process 관점에서 조회해본다.&lt;/p&gt;
&lt;pre class=&quot;dos&quot;&gt;&lt;code&gt;ps aux&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;역시 &lt;code&gt;kata-worker1&lt;/code&gt; Node에서 수행&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;root       71901  0.0  0.1 1238360 15332 ?       Sl   23:54   0:00 /usr/local/bin/containerd-shim-runc-v2 -namespace k8s.io -id 7ac6791ddd34560db31db2c1c62c7428387b2bfdcfc78cadebb0363bcdc48b3b -address /run/containerd/containerd.sock
65535      71925  0.0  0.0    996   640 ?        Ss   23:54   0:00 /pause
root       72001  0.0  0.0  11472  7552 ?        Ss   23:54   0:00 nginx: master process nginx -g daemon off;
message+   72036  0.0  0.0  11936  3052 ?        S    23:54   0:00 nginx: worker process
message+   72037  0.0  0.0  11936  3052 ?        S    23:54   0:00 nginx: worker process
message+   72038  0.0  0.0  11936  3052 ?        S    23:54   0:00 nginx: worker process
message+   72039  0.0  0.0  11936  3052 ?        S    23:54   0:00 nginx: worker process&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;kata 와 달리, &lt;code&gt;containerd-shim-runc-v2&lt;/code&gt; 와 &lt;code&gt;pause&lt;/code&gt; process 등을 확인할 수 있다!&lt;/li&gt;
&lt;/ul&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;/div&gt;</description>
      <category>Cloud/kubernetes (k8s)</category>
      <category>cloud</category>
      <category>container</category>
      <category>k8s</category>
      <category>kata-container</category>
      <category>Kubernetes</category>
      <author>aoc55.soft@gmail.com</author>
      <guid isPermaLink="true">https://aoc55.tistory.com/73</guid>
      <comments>https://aoc55.tistory.com/73#entry73comment</comments>
      <pubDate>Wed, 20 Aug 2025 00:18:33 +0900</pubDate>
    </item>
    <item>
      <title>k8s :: kata container (v3) 설치 해보기 with k8s - #1</title>
      <link>https://aoc55.tistory.com/72</link>
      <description>&lt;p style=&quot;position: absolute;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;position: absolute;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class=&quot;markdown-body&quot;&gt;
&lt;h1&gt;#1. kata v3 + QEMU 기반으로 직접 설치해보기&lt;/h1&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;280&quot; data-origin-height=&quot;280&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mNuwr/btsPYAjpvfF/1ygmdBTTfVPz8EKoZfF2ak/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mNuwr/btsPYAjpvfF/1ygmdBTTfVPz8EKoZfF2ak/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mNuwr/btsPYAjpvfF/1ygmdBTTfVPz8EKoZfF2ak/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmNuwr%2FbtsPYAjpvfF%2F1ygmdBTTfVPz8EKoZfF2ak%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;280&quot; height=&quot;280&quot; data-origin-width=&quot;280&quot; data-origin-height=&quot;280&quot;/&gt;&lt;/span&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;순수 Ubuntu 만 설치되어 있는 Host 환경에서, 직접 &lt;b&gt;v3 기반의 kata container&lt;/b&gt; 와 &lt;b&gt;containerd&lt;/b&gt; 설치를 통해 &lt;b&gt;Micro VM 기반의 Container&lt;/b&gt;를 직접 생성해본다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1-0 :: 목표 및 실습 환경&lt;/h2&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;&lt;b&gt;kata runtime 3.0&lt;/b&gt;을 &quot;Host&quot;에 직접 설치하기&lt;/li&gt;
&lt;li&gt;그리고 MicroVM을 생성하기 위해 VMM으로 &lt;b&gt;QEMU&lt;/b&gt; 사용(연동)하기&lt;/li&gt;
&lt;li&gt;(즉, 이번 실습에서, kata v3의 가장 큰 특징 중 하나인 &lt;b&gt;Dragonball&lt;/b&gt;&lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;을&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;사용하지 않고 기존 &lt;b&gt;QEMU&lt;/b&gt; 기반으로 실습)&lt;/li&gt;
&lt;/ul&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;현재('25.08) 아래 링크를 보면, rust 기반인 &lt;b&gt;3.x&lt;/b&gt; 설치의 경우 &lt;b&gt;Source를 통해 직접 설치만 가능&lt;/b&gt;하다.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/kata-containers/kata-containers/blob/main/docs/install/kata-containers-3.0-rust-runtime-installation-guide.md#automatic-installation&quot;&gt;kata-containers/docs/install/kata-containers-3.0-rust-runtime-installation-guide.md at main &amp;middot; kata-containers/kata-containers &amp;middot; GitHub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&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;참고로 아래 실습은 &lt;span style=&quot;color: #1b711d;&quot;&gt;&lt;b&gt;ubuntu noble (24.04) 기반&lt;/b&gt;&lt;/span&gt;으로 진행.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1-1 :: 사전 패키지 설치 및 설정&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;kata runtime 을 설치 하기 전, &lt;code&gt;QEMU&lt;/code&gt;와 같이 필요한 &lt;b&gt;사전 패키지를 설치&lt;/b&gt;한다.&lt;br /&gt;(아래 진행은 &lt;span style=&quot;color: #1b711d;&quot;&gt;&lt;b&gt;ubuntu noble&lt;/b&gt;&lt;/span&gt; 기준으로 진행)&lt;/p&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;sudo apt update
sudo apt install -y \
    qemu-system-x86 \
    qemu-utils \
    virtiofsd&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;virtiofsd&lt;/code&gt; 의 경우 noble 부터, qemu 설치 이후에도 별도 설치를 해주어야 한다.&lt;/li&gt;
&lt;li&gt;정상 설치가 되었는지 확인
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;qemu-system-x86_64 --version&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dpkg -L virtiofsd | grep virtiofsd&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;app armor 비 활성화&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;실습상 편의를 위해, app-armor는 비활성화한다.&lt;/li&gt;
&lt;li&gt;(단, 준비된 환경의 OS Verison 에 따라 다를 수 있음)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;sudo rm -rf /etc/apparmor.d/*
sudo systemctl stop apparmor
sudo systemctl disable apparmor&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;vala&quot;&gt;&lt;code&gt;# sudo vi /etc/default/grub

# ...
# 아래와 같이 apparmor=0 추가
GRUB_CMDLINE_LINUX_DEFAULT=&quot;quiet splash apparmor=0&quot;
# ...&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;sudo update-grub
sudo reboot now&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1-2 :: Rust 환경 준비&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;v3에서는 kata의 runtime이 &lt;code&gt;go&lt;/code&gt; 가 아닌 &lt;code&gt;rust&lt;/code&gt; 기반으로 작성 되었기에, 우선 &lt;code&gt;rust&lt;/code&gt; 가 실행 가능한 환경을 setup 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;rust&lt;/code&gt; Version 설정&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;export RUST_VERSION=1.85.1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;Rustup&lt;/code&gt; 다운로드 및 &lt;code&gt;rust&lt;/code&gt; 설치&lt;/p&gt;
&lt;pre class=&quot;mel&quot;&gt;&lt;code&gt;curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# 이후 shell 내 1 입력

source $HOME/.cargo/env
rustup install ${RUST_VERSION}
rustup default ${RUST_VERSION}-x86_64-unknown-linux-gnu

rustup target add x86_64-unknown-linux-musl&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;표준 라이브러리 (&lt;code&gt;Musl&lt;/code&gt;, &lt;code&gt;libc&lt;/code&gt;) 설치&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;wget https://musl.libc.org/releases/musl-1.2.3.tar.gz

tar vxf musl-1.2.3.tar.gz

cd musl-1.2.3/

./configure --prefix=/usr/local/

make &amp;amp;&amp;amp; sudo make install&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1-3 :: kata runtime 설치&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전 &lt;code&gt;rust&lt;/code&gt; 환경 준비가 끝났으면, 이제 본격적으로 kata runtime을 설치 할 차례이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 git을 통해서 Code 를 가져온다.&lt;/p&gt;
&lt;pre class=&quot;crmsh&quot;&gt;&lt;code&gt;git clone https://github.com/kata-containers/kata-containers.git&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 &lt;code&gt;make install&lt;/code&gt; 을 진행하는데, &lt;code&gt;v3&lt;/code&gt; 기본인 &lt;code&gt;Dragonball VMM&lt;/code&gt;을 사용하지 않고, 기존 &lt;code&gt;QEMU&lt;/code&gt; 기반으로 연동 하기 위해 아래와 같이 추가 옵션을 설정한 뒤 진행한다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;cd kata-containers/src/runtime-rs

# Build
make USE_BUILDIN_DB=false

# Install
make install HYPERVISOR=qemu&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치 시 아래와 같은 콘솔 출력을 확인할 수 있다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3284&quot; data-origin-height=&quot;2148&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FkgNh/btsPZetxLQV/wCI0Tdo4XY2LxhDqPdmF2k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FkgNh/btsPZetxLQV/wCI0Tdo4XY2LxhDqPdmF2k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FkgNh/btsPZetxLQV/wCI0Tdo4XY2LxhDqPdmF2k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFkgNh%2FbtsPZetxLQV%2FwCI0Tdo4XY2LxhDqPdmF2k%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;785&quot; height=&quot;513&quot; data-origin-width=&quot;3284&quot; data-origin-height=&quot;2148&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;h2 data-ke-size=&quot;size26&quot;&gt;1-4 :: kata runtime 정상 설치 확인&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 kata runtime 이 정상적으로 설치 되었는 지 확인하자.&lt;/p&gt;
&lt;pre class=&quot;bash&quot;&gt;&lt;code&gt;which containerd-shim-kata-v2
# /usr/local/bin/containerd-shim-kata-v2&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;containerd-shim-kata-v2 --version
# Kata Containers containerd shim (Rust): id: io.containerd.kata.v2, version: 3.19.1, commit: c92bb1aa88fa75005524575de3d192fe747dd3e7&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;참고로 v3 (Rust) 기반이여도, 이름은 &lt;code&gt;containerd-shim-kata-v2&lt;/code&gt; 이다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;v2&lt;/code&gt; 의 의미는 &lt;code&gt;containerd&lt;/code&gt; 의 &lt;code&gt;v2&lt;/code&gt; 인터페이스를 준수한다는 의미이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1-5 :: MicroVM 생성을 위한 Kernel &amp;amp; Image 다운로드 및 설정&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;kata 기반으로 Container Process 를 실행하기 위해, 기반이 되는 &lt;b&gt;Micro VM이 사용할 커널과 OS Image가 필요하다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 위해 직접 Kernerl 과 Image &amp;amp; rootfs 를 제작할 수도 있고, 이미 생성된 것을 사용할 수도 있다. (직접 제작을 위해서는 kata-container 내 docs 를 참고하면 된다)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해당 실습에서는 사전에 제작된 kernel과 image를 다운로드 받은 뒤, runtime이 사용할 수 있게 설정&lt;/b&gt;하는 방식으로 진행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다운로드 받을 커널과 이미지는 아래 링크의 &lt;code&gt;Assets&lt;/code&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;a href=&quot;https://github.com/kata-containers/kata-containers/releases&quot;&gt;Releases &amp;middot; kata-containers/kata-containers&lt;/a&gt;&lt;b&gt;&lt;i&gt; &amp;gt; kata-static-3.19.1-amd64.tar.xz&lt;/i&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;cd ~ 

# 다운로드
wget https://github.com/kata-containers/kata-containers/releases/download/3.19.1/kata-static-3.19.1-amd64.tar.xz

# 압축 해제
tar -xf kata-static-3.19.1-amd64.tar.xz&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 압축 해제 된 디렉터리에 들어가면, 아래와 같이 필요한 커널과 이미지를 확인할 수 있다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;# 파일 확인
cd ~/opt/kata/share/kata-containers
tree .
.
# ...
├── kata-ubuntu-noble.image
├── kata-ubuntu-noble-nvidia-gpu-575.64.03.initrd
├── kata-ubuntu-noble-nvidia-gpu-confidential-575.64.03.initrd
├── root_hash.txt
├── vmlinux-6.12.36-160
├── vmlinux-6.12.36-160-confidential
# ...&lt;/code&gt;&lt;/pre&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; : &lt;code&gt;vmlinux-6.12.36-160&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Image&lt;/b&gt; : &lt;code&gt;kata-ubuntu-noble.image&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다운 받은 위 파일들을, kata runtime이 사용할 수 있도록 하기 위해 아래와 같은 (기본) 경로로 복사한다.&lt;/p&gt;
&lt;pre class=&quot;dts&quot;&gt;&lt;code&gt;mkdir -p /usr/share/kata-containers/

# kernel
cp ~/opt/kata/share/kata-containers/vmlinux-6.12.36-160 \
    /usr/share/kata-containers/vmlinux.container

# image
cp ~/opt/kata/share/kata-containers/kata-ubuntu-noble.image \
    /usr/share/kata-containers/kata-containers.img&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;잘 복사 되었는지 확인.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;# 확인
ls -alh /usr/share/kata-containers/

total 521M
drwxr-xr-x   2 root root 4.0K Aug 19 00:44 .
drwxr-xr-x 148 root root 4.0K Aug 19 00:44 ..
-rw-r--r--   1 root root 256M Aug 19 00:44 kata-containers.img
-rw-r--r--   1 root root 265M Aug 19 00:44 vmlinux.container&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 kata-runtime의 설정을 위해 &lt;code&gt;configuration.toml&lt;/code&gt; 을 생성한다.&lt;/p&gt;
&lt;pre class=&quot;gradle&quot;&gt;&lt;code&gt;mkdir -p /etc/kata-containers
cp -f /usr/share/defaults/kata-containers/runtime-rs/configuration-qemu-runtime-rs.toml /etc/kata-containers/configuration.toml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 qemu를 통해 Mirco VM을 생성하기 위한 &lt;b&gt;QEMU, 커널, 이미지 경로가 제대로 구성 되어 있는 지 확인 및 수정&lt;/b&gt;한다.&lt;/p&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;# vim /etc/kata-containers/configuration.toml

[hypervisor.qemu]
path = &quot;/usr/bin/qemu-system-x86_64&quot;
kernel = &quot;/usr/share/kata-containers/vmlinux.container&quot;
image = &quot;/usr/share/kata-containers/kata-containers.img&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;ls -alh /usr/share/kata-containers/&lt;/code&gt; 내 실제 파일과 비교하면서 정상적으로 설정되었는지 검토.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1-6 :: Containerd 설치&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;kata-runtime 설치가 완료되었으므로, 이어서 해당 runtime을 제어 할 &lt;b&gt;Containerd&lt;/b&gt; 설치를 진행한다.&lt;/p&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;cd ~

wget https://github.com/containerd/containerd/releases/download/v1.7.28/containerd-1.7.28-linux-amd64.tar.gz

tar Cxzvf /usr/local containerd-1.7.28-linux-amd64.tar.gz&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Containerd &lt;code&gt;1.7.28&lt;/code&gt; 버전 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치 이후에, Containerd를 위한 &lt;code&gt;systemd&lt;/code&gt; Service 파일을 다운 받은 뒤 활성화(enable &amp;amp; start) 한다.&lt;/p&gt;
&lt;pre class=&quot;crystal&quot;&gt;&lt;code&gt;wget https://raw.githubusercontent.com/containerd/containerd/main/containerd.service

cp containerd.service /usr/lib/systemd/system/

systemctl daemon-reload
systemctl enable containerd
systemctl start containerd&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이후 &lt;code&gt;systemctl status containerd&lt;/code&gt; 통해서 정상적으로 실행되었는 지 확인한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1-7 :: Containerd - kata runtime 설정&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Containerd를 설치하였으니, 이제 Containerd가 Runtime으로 &lt;code&gt;kata&lt;/code&gt; 를 사용할 수 있도록 설정을 진행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 Containerd 설정 파일을 추출한다. &lt;i&gt;(혹시 이미 존재한다면 생략)&lt;/i&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml &amp;gt;/dev/null&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 kata runtime 과 호환을 위해 아래와 같이 &lt;b&gt;Containerd 내 설정&lt;/b&gt;을 진행한다.&lt;/p&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;# vim /etc/containerd/config.toml

[plugins]
  [plugins.&quot;io.containerd.grpc.v1.cri&quot;]
    [plugins.&quot;io.containerd.grpc.v1.cri&quot;.containerd]
      default_runtime_name = &quot;kata&quot;
      [plugins.&quot;io.containerd.grpc.v1.cri&quot;.containerd.runtimes]
        [plugins.&quot;io.containerd.grpc.v1.cri&quot;.containerd.runtimes.kata]
          runtime_type = &quot;io.containerd.kata.v2&quot;&lt;/code&gt;&lt;/pre&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; - &lt;a href=&quot;https://github.com/kata-containers/kata-containers/blob/main/docs/install/container-manager/containerd/containerd-install.md&quot;&gt;kata-containers/docs/install/container-manager/containerd/containerd-install.md at main &amp;middot; kata-containers/kata-containers &amp;middot; GitHub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1246&quot; data-origin-height=&quot;1506&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cJmmAP/btsPWZqT6jr/VJN2TH4GLjno40p459MkC1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cJmmAP/btsPWZqT6jr/VJN2TH4GLjno40p459MkC1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cJmmAP/btsPWZqT6jr/VJN2TH4GLjno40p459MkC1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcJmmAP%2FbtsPWZqT6jr%2FVJN2TH4GLjno40p459MkC1%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;775&quot; height=&quot;937&quot; data-origin-width=&quot;1246&quot; data-origin-height=&quot;1506&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;이후 containerd를 재시작한다.&lt;/p&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;systemctl daemon-reload
systemctl restart containerd&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1-8 :: Containerd 를 통해 kata 기반의 Container 생성해보기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기까지 진행했다면, &lt;b&gt;kata runtime 설치와 이를 제어 할 Containerd를 모두 설치하였으니 실제 생성을 해보자.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테스트에 사용할 Container의 Image는 &lt;code&gt;nginx&lt;/code&gt;를 사용한다.&lt;/p&gt;
&lt;pre class=&quot;groovy&quot;&gt;&lt;code&gt;ctr image pull docker.io/library/nginx:latest&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;dockerfile&quot;&gt;&lt;code&gt;ctr run --runtime &quot;io.containerd.kata.v2&quot; \
    --d docker.io/library/nginx:latest \
        test-kata-nginx&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;--runtime &quot;io.containerd.kata.v2&quot;&lt;/code&gt; 지정하는 것을 확인하자.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 Container가 정상적으로 생성 되었는지 확인해보자.&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;ctr c list
# ---
CONTAINER          IMAGE                             RUNTIME
test-kata-nginx    docker.io/library/nginx:latest    io.containerd.kata.v2&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;정상 생성 되었다면 Container 안에 들어가서 &lt;code&gt;nginx&lt;/code&gt; 가 맞는 지 확인하자.&lt;/p&gt;
&lt;pre class=&quot;bash&quot;&gt;&lt;code&gt;ctr t exec --exec-id test -t test-kata-nginx /bin/sh&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;xml&quot;&gt;&lt;code&gt;cat /usr/share/nginx/html/index.html

&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;title&amp;gt;Welcome to nginx!&amp;lt;/title&amp;gt;
# ...&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;nginx&lt;/code&gt; Container가 정상적으로 생성되었음을 알 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #1b711d;&quot;&gt;&lt;i&gt;&lt;b&gt;단, 별도의 Container Network 작업은 되어 있지 않은 상태라, &lt;code&gt;:80&lt;/code&gt; 통해서 nginx 서비스 등은 불가능한 상태다.&amp;nbsp;&lt;br /&gt;(이는 #2. 에서 k8s 구성 이후 수행)&lt;/b&gt;&lt;/i&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;b&gt;Host에서 Process 조회 해보기&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;dos&quot;&gt;&lt;code&gt;ps aux&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;아래 결과를 보면 알 수 있듯이, &amp;nbsp;&lt;code&gt;nginx&lt;/code&gt; Container Process 를 위한,&lt;b&gt; Micro VM이 qemu로 실행되었음을 알 수 있다.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;root       15502  0.2  0.2  70700 23552 ?        Sl   00:49   0:00 /usr/local/bin/containerd-shim-kata-v2 -id test-kata-nginx -namespace default -address /run/containerd/containerd.sock -publish-binary /usr/local/bin/containerd
root       15508  0.0  0.2 2306624 17280 ?       Sl   00:49   0:00 /usr/libexec/virtiofsd --socket-path virtiofsd.sock --shared-dir /run/kata-containers/shared/sandboxes/test-kata-nginx/ro --cache auto --sandbox none --seccomp none --thread-pool-size=1 -o announce_submounts
root       15512  1.4  2.5 2939816 201240 ?      Sl   00:49   0:02 /usr/bin/qemu-system-x86_64 -name sandbox-test-kata-nginx -kernel /usr/share/kata-containers/vmlinux.container -append reboot=k panic=1 systemd.unit=kata-containers.target systemd.mask=systemd-networkd.service root=/dev/pmem0p1 rootf&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;a title=&quot;k8s :: kata container (v3) 설치 해보기 - #2&quot; href=&quot;https://aoc55.tistory.com/73&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://aoc55.tistory.com/73&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Cloud/kubernetes (k8s)</category>
      <category>cloud</category>
      <category>container</category>
      <category>k8s</category>
      <category>kata-container</category>
      <category>Kubernetes</category>
      <author>aoc55.soft@gmail.com</author>
      <guid isPermaLink="true">https://aoc55.tistory.com/72</guid>
      <comments>https://aoc55.tistory.com/72#entry72comment</comments>
      <pubDate>Tue, 19 Aug 2025 23:24:28 +0900</pubDate>
    </item>
    <item>
      <title>Openstack :: Heat Study (1)</title>
      <link>https://aoc55.tistory.com/71</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class=&quot;markdown-body&quot;&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개인적으로 공부하는 관점에서 작성한 내용이라, 잘못된 부분이 있을 수 있습니다. 잘못된 부분은 말씀주시면 감사하겠습니다&lt;/p&gt;
&lt;/blockquote&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;&lt;a href=&quot;https://docs.openstack.org/heat/latest/&quot;&gt;https://docs.openstack.org/heat/latest/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://wikidocs.net/230737&quot;&gt;https://wikidocs.net/230737&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://somaz.tistory.com/383&quot;&gt;https://somaz.tistory.com/383&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.redhat.com/ko/documentation/red_hat_openstack_platform/16.1/html/advanced_overcloud_customization/assembly_understanding-heat-templates#con_heat-templates_understanding-heat-templates&quot;&gt;https://docs.redhat.com/ko/documentation/red_hat_openstack_platform/16.1/html/advanced_overcloud_customization/assembly_understanding-heat-templates&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Heat Concept&lt;/h1&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;150&quot; data-origin-height=&quot;150&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bHmKiC/btsN1Q2FTIK/SsyA3XucIRJv2IaIF9cILk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bHmKiC/btsN1Q2FTIK/SsyA3XucIRJv2IaIF9cILk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bHmKiC/btsN1Q2FTIK/SsyA3XucIRJv2IaIF9cILk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbHmKiC%2FbtsN1Q2FTIK%2FSsyA3XucIRJv2IaIF9cILk%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;150&quot; height=&quot;150&quot; data-origin-width=&quot;150&quot; data-origin-height=&quot;150&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1139&quot; data-origin-height=&quot;537&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/brcHoU/btsN2kCcwfZ/zj9ONHjYeLIKbVw6e1oBpK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/brcHoU/btsN2kCcwfZ/zj9ONHjYeLIKbVw6e1oBpK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/brcHoU/btsN2kCcwfZ/zj9ONHjYeLIKbVw6e1oBpK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbrcHoU%2FbtsN2kCcwfZ%2Fzj9ONHjYeLIKbVw6e1oBpK%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;1139&quot; height=&quot;537&quot; data-origin-width=&quot;1139&quot; data-origin-height=&quot;537&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Heat는 결국 &lt;i&gt;Orchestrtation as a Service&lt;/i&gt;를 위한 Openstack Component!&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 위해 &lt;code&gt;Template&lt;/code&gt; 을 통해 정의하고,&lt;code&gt;Stack&lt;/code&gt; 이라는 실제 Instance를 생성해서 구성 및 관리하는 것으로 보인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&quot;HOT&quot; (Heat Orchestration Template)&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;&lt;code&gt;YAML&lt;/code&gt; or &lt;code&gt;JSON&lt;/code&gt;으로 작성이 가능한데, 대부분 &lt;code&gt;YAML&lt;/code&gt; 으로 작성 하는 것으로 보임&lt;/li&gt;
&lt;li&gt;특징으로 &lt;code&gt;AWS CloudFormation&lt;/code&gt; 호환이 됨&lt;/li&gt;
&lt;li&gt;Template 구성 시 조건부/조건문, 중첩구조 등이 가능함&lt;/li&gt;
&lt;/ul&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;(참고) AWS CloudFormation 호환 관련해서는, 공식 Component Docs 내 아래와 같은 문구도 볼 수 있음&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #666666; text-align: center;&quot;&gt;현재 OpenStack에는 CloudFormation을 구현한 다른 프로젝트가 존재하지 않습니다. 개발자들은 클라우드 개발자들이 AWS에서 OpenStack 배포 환경으로 워크로드를 이전하고자 하는 강한 요구가 있다고 믿고 있습니다. OpenStack에서 잘 구현되고 통합된 CloudFormation API가 부재한 상황에서, 우리는 이 공백을 메우는 고품질 구현을 제공함으로써 OpenStack의 보편성을 향상시키고자 합니다.&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&quot;Stack&quot;&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;위 &lt;code&gt;HOT&lt;/code&gt; Template에 정의된대로 생성된 실제 Infrastructure (Server, Network, Port...)들을 의미&lt;/li&gt;
&lt;li&gt;단, 위 &lt;code&gt;HOT&lt;/code&gt; 통해서 일관되고 반복적으로 여러 &lt;code&gt;Stack&lt;/code&gt;생성 등이 가능하다. (쓰는 이유 중 가장 중요한 점일듯..)&lt;/li&gt;
&lt;/ul&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;code&gt;Stack&lt;/code&gt; 리소스 기반으로 &lt;b&gt;Auto Scaling 기능&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;단, Auto Scaling을 위해서는 Metrics 등이 수집되고 관리되어야 하는데 이를 위해서 &lt;code&gt;Ceilometer&lt;/code&gt;, &lt;code&gt;Aodh&lt;/code&gt; 등과 같은 요소들이 함께 필요한 것으로 보임.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Heat 사용에 대한 장점&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대부분의 Application은, 단일 Layer가 아닌 Mutli Layer 기반으로 구성됨.&lt;br /&gt;이를 위해서는(Application 의) Infrastructure 관점에서도 &lt;b&gt;복잡한 구조&lt;/b&gt;를 가지게 됨.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 &lt;code&gt;WEB&lt;/code&gt; - &lt;code&gt;WAS&lt;/code&gt; - &lt;code&gt;DB&lt;/code&gt; 와 같은 (이제는.. Classiscal 하지만...) 3 Layer 구조를 Openstack 에서 형성하기 위해서는... &lt;b&gt;(짧게 생각해도) 아래와 같이 Openstack 관점에서는 많은 구성 작업들이 필요함.&lt;/b&gt;&lt;/p&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;Layer 별로 &lt;code&gt;Network&lt;/code&gt; 혹은 &lt;code&gt;Subnet&lt;/code&gt; 을 분리하고,&lt;/li&gt;
&lt;li&gt;서로 통신이 가능하도로 &lt;code&gt;Router&lt;/code&gt;를 생성한 뒤 각각의 &lt;code&gt;Subnet&lt;/code&gt;을 연결하고,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Port&lt;/code&gt;를 생성하는데, 추가로 &lt;code&gt;Security Group&lt;/code&gt; 등으로 ACL을 제어하고,&lt;/li&gt;
&lt;li&gt;이후 각각 &lt;code&gt;Server&lt;/code&gt;, &lt;code&gt;Volume&lt;/code&gt;을 생성하고,&lt;/li&gt;
&lt;li&gt;또한 Ocatavia 기반의 &lt;code&gt;LB&lt;/code&gt;를 연결하고...&lt;/li&gt;
&lt;li&gt;등등등 ........&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 &lt;code&gt;Heat&lt;/code&gt; 를 통해서, 위와 같은 &lt;b&gt;복잡한 구조의 인프라 배포 및 구성을 (Openstack 관점에서) 쉽게 할 수 있음&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;거기에 &lt;code&gt;Template&lt;/code&gt; 구조를 통해서 Auto Scaling 뿐만아니라, 장애 등의 상황에서 자동으로 리소스 복구가 가능한 구조임.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;즉, &lt;u&gt;관리의 단순화&lt;/u&gt; + &lt;u&gt;인프라스트럭처 배포 및 운영의 자동화&lt;/u&gt; 등의 장점이 있음&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;Heat Architecture&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Heat Services&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;ref. &lt;/b&gt;&lt;a href=&quot;https://docs.openstack.org/heat/latest/developing_guides/architecture.html&quot;&gt;https://docs.openstack.org/heat/latest/developing_guides/architecture.html&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;code&gt;Heat&lt;/code&gt; 를 구성하기 위해서 어떠한 &lt;code&gt;Service&lt;/code&gt; 들이 구성되어 있는가?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;heat&lt;/code&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Heat 서비스들에 대한 CLI 도구&lt;/li&gt;
&lt;li&gt;&lt;code&gt;heat-api&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Openstack Natvie 한 Heat API 제공의 역할 (즉, api-server)&lt;/li&gt;
&lt;li&gt;API 요청을 수신할 경우 RPC 통신을 통해, &lt;code&gt;heat-engine&lt;/code&gt; Service를 호출하는 구조&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;heat-api-cfn&lt;/code&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;code&gt;cfn&lt;/code&gt; -&amp;gt; &quot;&lt;i&gt;CloudFormation&lt;/i&gt;&quot;&lt;/li&gt;
&lt;li&gt;AWS CloudFormation과 호환되는 AWS Query API를 제공하는 목적&lt;/li&gt;
&lt;li&gt;역시 동일하게 API 요청 수신 시, RPC 통신으로 Heat Engine 으로 전송&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;heat-engine&lt;/code&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Orchestrate (template 실행 등)에 대한 Main 책임을 가지는 서비스임.&lt;/li&gt;
&lt;li&gt;오케스트레이션 관련해서 API Consumer에게 Event 제공도 해주고 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Heat Agent를 활용한 Configuration&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주 목적은 배포 된 Server 내에 (&lt;code&gt;Agent&lt;/code&gt; 기반으로) 필요한 &quot;&lt;b&gt;Software Configuration&lt;/b&gt;&quot; 을 실행하기 위함.&lt;br /&gt;즉, Heat를 통해서 Infrastrucutre의 배포 뿐만 아니라, &lt;b&gt;Software Config 까지 수행이 가능하다.&lt;/b&gt;&lt;br /&gt;(간단한 예시로 특정 패키지 설치, 설정파일 배포, 특정 커맨드 실행)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단, 이를 위해서 생성한 &lt;code&gt;Server&lt;/code&gt; 내 아래와 같은 Agent 설치 및 구성이 필요하다.&lt;br /&gt;Server 내에서 Agent 설치를 위해선, Agent 설치는 Cloud-Init을 사용하거나 사전 설치 후 전용 Image 를 구성하는 등의 방식이 필요해보임&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Heat Agent&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;&lt;code&gt;Template&lt;/code&gt; -&amp;gt; &lt;code&gt;Stack&lt;/code&gt; 으로 생성된 &lt;code&gt;Server&lt;/code&gt; 내부에서 동작하는 Agent.&lt;/li&gt;
&lt;li&gt;Agent 종류
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;os-collect-config&lt;/code&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;li&gt;&lt;code&gt;os-refresh-config&lt;/code&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;변경 설정 감지 -&amp;gt; &lt;code&gt;os-apply-config&lt;/code&gt; 실행 트리거&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;os-apply-config&lt;/code&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;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Agent 구성 이후 사용 가능한,&lt;code&gt;Template&lt;/code&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;Agent 구성 이후, &lt;code&gt;Template&lt;/code&gt; 내에서 아래와 같은 리소스 타입 구성들을 통해서 필요한 작업을 구성할 수 있다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;type: OS::Heat::SoftwareConfig&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;type: OS::Heat::SoftwareDeployment&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;예시 Template&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;dts&quot;&gt;&lt;code&gt;# 생략....
    resources:
      my_config:
        type: OS::Heat::SoftwareConfig
        properties:
          config: |
            #!/bin/bash
            echo &quot;Hello from Heat&quot; &amp;gt; /tmp/hello.txt

      my_deployment:
        type: OS::Heat::SoftwareDeployment
        properties:
          config: { get_resource: my_config }
          server: { get_resource: my_server }
# 생략....&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Template -&amp;gt; Agent 기반의 실행 절차 요약&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;lua&quot;&gt;&lt;code&gt;Heat Stack 생성 시
   &amp;darr;
heat-engine 이 SoftwareDeployment 리소스 생성
   &amp;darr;
heat-agent (예: os-collect-config) 가 주기적으로 설정 요청 확인
   &amp;darr;
설정 감지 시 os-apply-config 등을 통해 내부 명령 실행
   &amp;darr;
결과를 Heat API에 보고 (성공/실패 등)&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;Hands On&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;HOT (Heat Orchestration Template) 작성&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Template 기본 구조&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;공식 Docs&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;&lt;a href=&quot;https://docs.openstack.org/heat/2025.1/template_guide/hot_guide.html#a-most-basic-template&quot;&gt;https://docs.openstack.org/heat/2025.1/template_guide/hot_guide.html#a-most-basic-template&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Template 기본 구조&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;heat_template_version: 2016-10-14

description:
# a description of the template

parameter_groups:
# a declaration of input parameter groups and order

parameters:
# declaration of input parameters

resources:
# declaration of template resources

outputs:
# declaration of output parameters

conditions:
# declaration of conditions&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;heat_template_version&lt;/code&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Template 규격에 대한 Version 을 정의&lt;/li&gt;
&lt;li&gt;현재 작성 시점 기준으로는 &lt;code&gt;2021-04-16&lt;/code&gt;가 마지막 최신 Version 인 것 같다.&lt;/li&gt;
&lt;li&gt;다만, 버전 별로 지원되는 템플릿 렌더링 메서드나 구조에서 차이가 있을 수 있으니 이 부분은 미리 확인이 필요해보인다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;resources&lt;/code&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;해당 Template 을 통해서 생성할 실제 Resource들을 정의&lt;/li&gt;
&lt;li&gt;ref.&amp;nbsp;&lt;a href=&quot;https://docs.openstack.org/heat/2025.1/template_guide/hot_spec.html#wallaby&quot;&gt;https://docs.openstack.org/heat/2025.1/template_guide/hot_spec.html#wallaby&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;resource 정의 시 위 문서를 참고해서&lt;/b&gt;, resource 별로 요구되는 properties 를 '직접' 혹은 '전달구조'로 전달해주면 된다.&lt;/li&gt;
&lt;li&gt;아래는 Network와 Subnet 에 대한 Resource 생성을 정의한 예시&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;dts&quot;&gt;&lt;code&gt;# 생략 ...

  # Network
  test01_network:
    type: OS::Neutron::Net
    properties:
      name: test01_network

  # Subnet
  test01_subnet:
    type: OS::Neutron::Subnet
    properties:
      name: test01_subnet
      network: { get_resource: test01_network }
      cidr: { get_param: my_net_cidr }
      ip_version: 4

# 생략 ...&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;Network&lt;/code&gt; 생성 한 이후, 해당 &lt;code&gt;Network&lt;/code&gt; 하위에 &lt;code&gt;Subnet&lt;/code&gt; 을 생성한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Subnet 생성 시점에, 상위 Network 리소스 정보를 얻기 위해서 { get_resource: test01_network } 와 같이 구성.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&lt;/span&gt;&lt;code style=&quot;letter-spacing: 0px;&quot;&gt;cidr&lt;/code&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt; 는 CLI를 통해 Template 에서 &lt;/span&gt;&lt;code style=&quot;letter-spacing: 0px;&quot;&gt;stack&lt;/code&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt; 리소스 생성 시 직접 파라미터로 입력 받게 함. (&lt;/span&gt;&lt;code style=&quot;letter-spacing: 0px;&quot;&gt;{ get_param: my_net_cidr }&lt;/code&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;이외에 &lt;/span&gt;&lt;code style=&quot;letter-spacing: 0px;&quot;&gt;properties&lt;/code&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt; 중 &lt;/span&gt;&lt;code style=&quot;letter-spacing: 0px;&quot;&gt;name&lt;/code&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt; 과 같은 부분은 상수 하드코딩(?) 하였음.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;직접 해본 예시 Template :: nginx 서버 구성하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;시나리오&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;code&gt;Tenant(self-service, overlay) Network&lt;/code&gt; 내 Web Server 역할을 수행할 &lt;code&gt;Server(VM)&lt;/code&gt;를 생성하고,&lt;/li&gt;
&lt;li&gt;사전에 정의한 외부 네트워크와 연결된 네트워크에서 &lt;code&gt;Floating IP&lt;/code&gt;를 할당해서, 최종적으로는 외부에서 접근 가능한 Web Server를 배포하는 예시&lt;/li&gt;
&lt;/ol&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1650&quot; data-origin-height=&quot;1014&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bIn8gu/btsN0DjdnCi/DNTcBm3gKXahlvzUS1kZzK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bIn8gu/btsN0DjdnCi/DNTcBm3gKXahlvzUS1kZzK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bIn8gu/btsN0DjdnCi/DNTcBm3gKXahlvzUS1kZzK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbIn8gu%2FbtsN0DjdnCi%2FDNTcBm3gKXahlvzUS1kZzK%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;1650&quot; height=&quot;1014&quot; data-origin-width=&quot;1650&quot; data-origin-height=&quot;1014&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;각 Resource 별로 Properites (필수, optional ...) 등은 역시 공식 문서 참고하면서 작성&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.openstack.org/heat/2025.1/template_guide/openstack.html&quot;&gt;https://docs.openstack.org/heat/2025.1/template_guide/openstack.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;figure id=&quot;og_1747469620957&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;OpenStack Resource Types &amp;mdash; openstack-heat 24.0.1.dev3 documentation&quot; data-og-description=&quot;use_request_body_as_input Available since 6.0.0 (Mitaka) Defines the method in which the request body for signaling a workflow would be parsed. In case this property is set to True, the body would be parsed as a simple json where each key is a workflow inp&quot; data-og-host=&quot;docs.openstack.org&quot; data-og-source-url=&quot;https://docs.openstack.org/heat/2025.1/template_guide/openstack.html&quot; data-og-url=&quot;https://docs.openstack.org/heat/2025.1/template_guide/openstack.html&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://docs.openstack.org/heat/2025.1/template_guide/openstack.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.openstack.org/heat/2025.1/template_guide/openstack.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&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;OpenStack Resource Types &amp;mdash; openstack-heat 24.0.1.dev3 documentation&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;use_request_body_as_input Available since 6.0.0 (Mitaka) Defines the method in which the request body for signaling a workflow would be parsed. In case this property is set to True, the body would be parsed as a simple json where each key is a workflow inp&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.openstack.org&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;&lt;i&gt;&lt;b&gt;샘플 Template&lt;/b&gt;&lt;/i&gt;&lt;/p&gt;
&lt;pre class=&quot;http&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot;&gt;&lt;code&gt;heat_template_version: 2018-08-31

description: &quot;Simple Heat Test1&quot;

parameters:
  # NW
  my_external_nw_name:
    type: string
    description: External Network ID for Router
  my_net_cidr:
    type: string
    description: Tenant Network cidr
  # Volume
  my_image_id:
    type: string
    description: Image ID for Instance
  my_volume_type:
    type: string
    description: Root Volume Type
  # Server
  my_public_key:
    type: string
    description: PublicKey
  my_flavor_id:
    type: string
    description: Flavor for Instance

resources:
  # Router
  test01_router:
    type: OS::Neutron::Router
    properties:
      name: test01_router
      external_gateway_info: {
        enable_snat: true,
        network: { get_param: my_external_nw_name }
      }

  # Network
  test01_network:
    type: OS::Neutron::Net
    properties:
      name: test01_network

  # Subnet
  test01_subnet:
    type: OS::Neutron::Subnet
    properties:
      name: test01_subnet
      network: { get_resource: test01_network }
      cidr: { get_param: my_net_cidr }
      ip_version: 4

  # Connect Subnet to Router
  router_interface:
    type: OS::Neutron::RouterInterface
    properties:
      router_id: { get_resource: test01_router }
      subnet_id: { get_resource: test01_subnet }

  # Security Group
  test01_sg:
    type: OS::Neutron::SecurityGroup
    properties:
      name: test01_sg
      rules:  [
        {
          direction: &quot;ingress&quot;,
          ethertype: &quot;IPv4&quot;,
          port_range_max: &quot;80&quot;,
          port_range_min: &quot;80&quot;,
          protocol: &quot;tcp&quot;,
          remote_ip_prefix: &quot;0.0.0.0/0&quot;,
          remote_mode: &quot;remote_ip_prefix&quot;
        },
        {
          direction: &quot;egress&quot;,
          ethertype: &quot;IPv4&quot;,
          port_range_min: &quot;1&quot;,
          port_range_max: &quot;65535&quot;,
          protocol: &quot;tcp&quot;,
          remote_ip_prefix: &quot;0.0.0.0/0&quot;,
          remote_mode: &quot;remote_ip_prefix&quot;
        },
        {
          direction: &quot;egress&quot;,
          ethertype: &quot;IPv4&quot;,
          port_range_min: &quot;1&quot;,
          port_range_max: &quot;65535&quot;,
          protocol: &quot;udp&quot;,
          remote_ip_prefix: &quot;0.0.0.0/0&quot;,
          remote_mode: &quot;remote_ip_prefix&quot;
        }
      ]

  # Port
  test01_port:
    type: OS::Neutron::Port
    properties:
      name: test01_port1
      network: { get_resource: test01_network }
      fixed_ips: [{ &quot;subnet&quot;: { get_resource: test01_subnet } }]
      security_groups: [{ get_resource: test01_sg }]

  # Floating IP
  test01_fip:
    type: OS::Neutron::FloatingIP
    properties:
      floating_network: { get_param: my_external_nw_name }

  # ---

  # Keypair
  test01_keypair:
    type: OS::Nova::KeyPair
    properties:
      name: test01_keypair
      public_key: { get_param: my_public_key }

  # Root Volume
  test01_root_volume:
    type: OS::Cinder::Volume
    properties:
      name: test01_root_volume
      image: { get_param: my_image_id }
      size: 40
      volume_type: { get_param: my_volume_type } 

  # Server
  test01_server:
    type: OS::Nova::Server
    properties:
      name: test01_server
      key_name: { get_resource: test01_keypair }
      flavor: { get_param: my_flavor_id }
      block_device_mapping_v2: [
        {
          delete_on_termination: True,
          volume_id: { get_resource: test01_root_volume }
        }
      ]
      networks: [{ port: { get_resource: test01_port }} ]
      user_data:
        str_replace:
          template: |
            #!/bin/bash
            apt update
            apt install -y nginx
            systemctl enable nginx
            systemctl start nginx
          params: {}

  # Associate Floating IP
  test01_fip_associate:
    type: OS::Neutron::FloatingIPAssociation
    properties:
      floatingip_id: { get_resource: test01_fip }
      port_id: { get_resource: test01_port }

outputs:
  test01_server:
    value: { get_attr: [ test01_server, name, networks ]}
  floating_ip:
    value: { get_attr: [ test01_fip, floating_ip_address ]}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc; color: #333333; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;VM 내 Nginx 구성은, 간단히 Cloud-Init 스크립트 기반으로 구성!&lt;/li&gt;
&lt;/ul&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;span style=&quot;color: #000000; font-size: 1.62em; letter-spacing: -1px;&quot;&gt;Heat CLI&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Template 에서 Stack 생성하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선, 작성한 Template에 오류가 없는지 검증하기 위해, Template 에서 정의한 &lt;code&gt;parameter&lt;/code&gt; 들을 같이 전달해서 &lt;code&gt;validate&lt;/code&gt; 를 수행해보자.&lt;/p&gt;
&lt;pre class=&quot;gams&quot;&gt;&lt;code&gt;openstack orchestration template validate -t /heat01.yaml \
  --parameter my_external_nw_name='provider-nw' \
  --parameter my_net_cidr='192.168.100.0/24' \
  --parameter my_image_id='c2ffc3d6-b84e-4fb6-a708-7e8562eeee10' \
  --parameter my_volume_type='rbd1' \
  --parameter my_flavor_id='29eb198c-e2ae-44e6-bce2-6f1b3fdb987b' \
  --parameter my_public_key=&quot;$(cat /test.pub)&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Heat 템플릿 문법 및 리소스 &lt;b&gt;검증&lt;/b&gt;을 수행&lt;/li&gt;
&lt;li&gt;별도의 오류가 없다면, 정상적으로 템플릿 구조 요약 출력&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 정의한 Template 파일를 통해서 실제로 &lt;code&gt;stack&lt;/code&gt; 리소스를 생성하자.&lt;/p&gt;
&lt;pre class=&quot;gams&quot;&gt;&lt;code&gt;openstack stack create -t /heat01.yaml \
  --parameter my_external_nw_name='provider-nw' \
  --parameter my_net_cidr='192.168.100.0/24' \
  --parameter my_image_id='c2ffc3d6-b84e-4fb6-a708-7e8562eeee10' \
  --parameter my_volume_type='rbd1' \
  --parameter my_flavor_id='29eb198c-e2ae-44e6-bce2-6f1b3fdb987b' \
  --parameter my_public_key=&quot;$(cat /test.pub)&quot; \
  my-stack-01  --wait&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;CLI 실행 결과&lt;/b&gt;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1270&quot; data-origin-height=&quot;1450&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zys2E/btsN0L2HlPy/kuMO6V3byhLKzxNs1LhT4k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zys2E/btsN0L2HlPy/kuMO6V3byhLKzxNs1LhT4k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zys2E/btsN0L2HlPy/kuMO6V3byhLKzxNs1LhT4k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fzys2E%2FbtsN0L2HlPy%2FkuMO6V3byhLKzxNs1LhT4k%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;1270&quot; height=&quot;1450&quot; data-origin-width=&quot;1270&quot; data-origin-height=&quot;1450&quot;/&gt;&lt;/span&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;&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;1650&quot; data-origin-height=&quot;1014&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1DT1G/btsN1tmzSbq/GTUerC54I91kQtd1KhMRK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1DT1G/btsN1tmzSbq/GTUerC54I91kQtd1KhMRK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1DT1G/btsN1tmzSbq/GTUerC54I91kQtd1KhMRK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1DT1G%2FbtsN1tmzSbq%2FGTUerC54I91kQtd1KhMRK1%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;1650&quot; height=&quot;1014&quot; data-origin-width=&quot;1650&quot; data-origin-height=&quot;1014&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;h3 data-ke-size=&quot;size23&quot;&gt;Stack 조회, 삭제 등..!&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 필요에 따라 생성한 &lt;code&gt;stack&lt;/code&gt; 리소스에 대해서 조회, 삭제 등을 수행이 가능&lt;/p&gt;
&lt;pre class=&quot;stata&quot;&gt;&lt;code&gt;# Stack 리스트 조회
openstack stack list

# Stack 상세 조회
openstack stack show &amp;lt;stack-name&amp;gt;

# 특정 Stack Event 조회
openstack stack evnet list &amp;lt;stack-name&amp;gt;

# 특정 Stack 삭제
openstack stack delete &amp;lt;stack-name&amp;gt;
# 그외 등...&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;Next  ...&lt;/h1&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;Ceilometer 와 연계해서, Auto Scaling 등 해보기!&lt;/li&gt;
&lt;li&gt;Heat engine 은 어떤 내부 구조로 리소스들이 생성되는 것을 감지하고 넘어가는 것일까?&lt;/li&gt;
&lt;li&gt;템플릿에서 -&amp;gt; 리소스 생성을 위한 Graph 구성은 어떤 방식으로 하는 것일까?&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;</description>
      <category>Cloud/Openstack</category>
      <category>cloud</category>
      <category>cloudnatvie</category>
      <category>Heat</category>
      <category>Infrastructure</category>
      <category>openinfra</category>
      <category>openstack</category>
      <category>오픈스택</category>
      <author>aoc55.soft@gmail.com</author>
      <guid isPermaLink="true">https://aoc55.tistory.com/71</guid>
      <comments>https://aoc55.tistory.com/71#entry71comment</comments>
      <pubDate>Sat, 17 May 2025 16:59:07 +0900</pubDate>
    </item>
    <item>
      <title>Openstack :: Keystone System Role</title>
      <link>https://aoc55.tistory.com/70</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class=&quot;markdown-body&quot;&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개인적으로 공부하는 관점에서 작성한 내용이라, 잘못된 부분이 있을 수 있습니다. 잘못된 부분은 말씀주시면 감사하겠습니다&lt;/p&gt;
&lt;/blockquote&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;&lt;a href=&quot;https://docs.openstack.org/keystone/latest/admin/service-api-protection.html&quot;&gt;Default Roles &amp;mdash; keystone 26.1.0.dev92 documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;300&quot; data-origin-height=&quot;226&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bXAylt/btsMjNgtPD3/xKllr0SPvPDJunvSHKG2t0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bXAylt/btsMjNgtPD3/xKllr0SPvPDJunvSHKG2t0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bXAylt/btsMjNgtPD3/xKllr0SPvPDJunvSHKG2t0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbXAylt%2FbtsMjNgtPD3%2FxKllr0SPvPDJunvSHKG2t0%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;300&quot; height=&quot;226&quot; data-origin-width=&quot;300&quot; data-origin-height=&quot;226&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1&gt;Keystone - System Role&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Openstack 의 RBAC 모델의 일부로서, Openstack의 &quot;전체적&quot;으로 제어하는 권한에 대한 정의&lt;br /&gt;즉, 특정 tenant 단위가 아닌 &lt;b&gt;Openstack 클러스터 수준에서 수행되는 작업의 제어하는 역할을 의미&lt;/b&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;참고&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Openstack 에서 Role 은 3가지 범위로 존재&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(1) System Scope&lt;/b&gt; -&amp;gt; Openstack Cluster 전체 관리를 위한 권한&lt;br /&gt;&lt;b&gt;(2) Domain Scope&lt;/b&gt; -&amp;gt; User / Group 관리를 위한 권한&lt;br /&gt;&lt;b&gt;(3) Project Scope&lt;/b&gt; -&amp;gt; Project(Tenant) 내의 리소스 관리를 위한 권한&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;System Role 적용 대상&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요약하면 &quot;&lt;b&gt;Openstack Cluster 전체&lt;/b&gt;&quot;에 영향을 미치는 작업을 수행&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;OpenStack 서비스 관리&lt;/b&gt; (예: Nova, Neutron, Glance, Cinder 등)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;사용자 및 역할(Role) 관리&lt;/b&gt; (예: Keystone에서 사용자 생성, 할당)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Openstack 클러스터의 전체 설정 변경&lt;/b&gt; (예: Nova 스케줄링 정책 변경)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;하이퍼바이저 와 같은 및 물리적 리소스 관리&lt;/b&gt; (예: Hypervisor, 네트워크 노드, 스토리지 노드)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;모든 Tenant 의 자원 조회&lt;/b&gt; (예: 전체 VM, 네트워크, 볼륨 조회 가능)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;그 외 등등..&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;System Role 종류&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래와 같이 3가지 Role 존재&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;system admin&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;Openstack 전체 및 최고 관리자 권한으로 페르소나로 보면 Operator/Cloud 관리자&lt;/li&gt;
&lt;li&gt;Openstack 서비스 (nova, cinder ..) 등 모든 서비스에 대한 관리 및 카탈로그 내 Endpoint 추가/삭제 등 가능&lt;/li&gt;
&lt;li&gt;그 외에 새로운 도메인 생성, 모든 User/Project/Role 등 관리 등 가능&lt;/li&gt;
&lt;li&gt;클러스터 내 모든 테넌트의 리소스 수정/삭제 등 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;system reader &amp;amp; system member&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;무엇보다 &quot;System 레벨&quot;에서는 member 와 reader 는 매우 유사한 권한 가지고 있음&lt;/li&gt;
&lt;li&gt;(&lt;i&gt;즉, system 권한에서 member 와 reader 간에 구분 지을만한 특징이 없다... 필요 시 일반적으로 reader 를 사용하는 것 같다?&lt;/i&gt;)&lt;/li&gt;
&lt;li&gt;두 권한의 가장 중요한 점은 Keystone 내의 모든 리소스(role assignments, users, projects, and group 등)에 대해서 조회가 가능하다는 점이다.&lt;/li&gt;
&lt;li&gt;페르소나로 보면 마치 Support Team 처럼 민감한 정보에 접근이 필요하지 않을 경우 유용하다 (혹은 Promehteus 처럼 모니터링 시스템?)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;관련 CLI 및 실습&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;User 생성 및 System Permission(Role) 부여&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;openstack user create system-user1
openstack role add --user system-user1 --system all admin

openstack user create system-user2
openstack role add --user system-user2 --system all member

openstack user create system-user3
openstack role add --user system-user3 --system all reader&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;--system all&lt;/code&gt; 을 통한 System Role 부여&lt;/li&gt;
&lt;/ul&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;System Permission(Role) 부여 확인&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;crmsh&quot;&gt;&lt;code&gt;openstack role assignment list --system all

openstack role assignment list --role admin --system all

openstack role assignment list --role member --system all

openstack role assignment list --role reader --system all&lt;/code&gt;&lt;/pre&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;971&quot; data-origin-height=&quot;230&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bCO3EN/btsMlCxDKo0/LZAMt2zGy0Ia7WQhAk1OVk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bCO3EN/btsMlCxDKo0/LZAMt2zGy0Ia7WQhAk1OVk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bCO3EN/btsMlCxDKo0/LZAMt2zGy0Ia7WQhAk1OVk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbCO3EN%2FbtsMlCxDKo0%2FLZAMt2zGy0Ia7WQhAk1OVk%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;971&quot; height=&quot;230&quot; data-origin-width=&quot;971&quot; data-origin-height=&quot;230&quot;/&gt;&lt;/span&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;&lt;b&gt;Skyline 에서 System Role 부여 조회&lt;/b&gt;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1706&quot; data-origin-height=&quot;950&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/menwr/btsMjPkYbvN/ZuzgQcOdPHwzLVbKHPVRbk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/menwr/btsMjPkYbvN/ZuzgQcOdPHwzLVbKHPVRbk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/menwr/btsMjPkYbvN/ZuzgQcOdPHwzLVbKHPVRbk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fmenwr%2FbtsMjPkYbvN%2FZuzgQcOdPHwzLVbKHPVRbk%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;1706&quot; height=&quot;950&quot; data-origin-width=&quot;1706&quot; data-origin-height=&quot;950&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;</description>
      <category>Cloud/Openstack</category>
      <category>cloud</category>
      <category>keystone</category>
      <category>openstack</category>
      <author>aoc55.soft@gmail.com</author>
      <guid isPermaLink="true">https://aoc55.tistory.com/70</guid>
      <comments>https://aoc55.tistory.com/70#entry70comment</comments>
      <pubDate>Sun, 16 Feb 2025 23:02:04 +0900</pubDate>
    </item>
  </channel>
</rss>