<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://juyoung-hong.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://juyoung-hong.github.io/" rel="alternate" type="text/html" /><updated>2026-07-17T20:20:43+09:00</updated><id>https://juyoung-hong.github.io/feed.xml</id><title type="html">Juyoung’s arXiv</title><subtitle>홍주영의 일기장</subtitle><author><name>Juyoung Hong</name><email>hjy_stat@naver.com</email></author><entry><title type="html">Coding 공부 - Java</title><link href="https://juyoung-hong.github.io/coding/coding_test_java/" rel="alternate" type="text/html" title="Coding 공부 - Java" /><published>2026-06-15T00:00:00+09:00</published><updated>2026-06-15T00:00:00+09:00</updated><id>https://juyoung-hong.github.io/coding/coding_test_java</id><content type="html" xml:base="https://juyoung-hong.github.io/coding/coding_test_java/"><![CDATA[<p><br /></p>

<h1 id="배열의-선언-및-초기화">배열의 선언 및 초기화</h1>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span><span class="o">[]</span> <span class="n">answer</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">int</span><span class="o">[</span><span class="mi">2</span><span class="o">];</span>
<span class="n">answer</span><span class="o">[</span><span class="mi">0</span><span class="o">]</span> <span class="o">=</span> <span class="n">a</span><span class="o">;</span>
<span class="n">answer</span><span class="o">[</span><span class="mi">1</span><span class="o">]</span> <span class="o">=</span> <span class="n">b</span><span class="o">;</span>

<span class="err">#</span> <span class="n">또는</span>
<span class="kt">int</span><span class="o">[]</span> <span class="n">answer</span> <span class="o">=</span> <span class="o">{};</span>
<span class="n">answer</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">int</span><span class="o">[]</span> <span class="o">{</span><span class="n">a</span><span class="o">,</span> <span class="n">b</span><span class="o">};</span>

<span class="err">#</span> <span class="n">또는</span>
<span class="kt">int</span><span class="o">[]</span> <span class="n">answer</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">int</span><span class="o">[]</span> <span class="o">{</span><span class="n">a</span><span class="o">,</span> <span class="n">b</span><span class="o">};</span>
</code></pre></div></div>

<h1 id="배열의-평균값">배열의 평균값</h1>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">java.util.Arrays</span><span class="o">;</span>

<span class="nc">Arrays</span><span class="o">.</span><span class="na">stream</span><span class="o">(</span><span class="n">numbers</span><span class="o">).</span><span class="na">average</span><span class="o">()</span>
  <span class="o">.</span><span class="na">orElse</span><span class="o">(</span><span class="mi">0</span><span class="o">);</span>
</code></pre></div></div>

<ul>
  <li>Arrays.stream(numbers).average():
    <ul>
      <li>numbers의 평균을 구합니다.</li>
    </ul>
  </li>
  <li>.orElse(0):
    <ul>
      <li>null인 경우, 0을 리턴합니다.</li>
    </ul>
  </li>
</ul>

<h1 id="longstream">LongStream</h1>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">java.util.stream.LongStream</span><span class="o">;</span>

<span class="nc">LongStream</span><span class="o">.</span><span class="na">range</span><span class="o">(</span><span class="mi">1</span><span class="o">,</span> <span class="n">num_list</span><span class="o">.</span><span class="na">length</span> <span class="o">+</span> <span class="mi">1</span><span class="o">)</span>
    <span class="o">.</span><span class="na">mapToInt</span><span class="o">(</span><span class="n">i</span> <span class="o">-&gt;</span> <span class="n">num_list</span><span class="o">[(</span><span class="kt">int</span><span class="o">)</span> <span class="o">(</span><span class="n">num_list</span><span class="o">.</span><span class="na">length</span> <span class="o">-</span> <span class="n">i</span><span class="o">)])</span>
    <span class="o">.</span><span class="na">toArray</span><span class="o">();</span>
</code></pre></div></div>

<ul>
  <li>LongStream.range(1, num_list.length + 1):
    <ul>
      <li>1부터 배열의 길이(num_list.length)까지의 숫자 시퀀스를 생성합니다.</li>
    </ul>
  </li>
  <li>.mapToInt(i -&gt; num_list[(int) (num_list.length - i)]):
    <ul>
      <li>생성된 각 숫자 i를 사용하여 배열의 인덱스에 접근합니다.</li>
    </ul>
  </li>
  <li>.toArray():
    <ul>
      <li>위의 과정을 통해 수집된 요소들을 다시 int[] 배열 형태로 변환하여 반환합니다.</li>
    </ul>
  </li>
</ul>

<h1 id="string">String</h1>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">String</span> <span class="n">answer</span> <span class="o">=</span> <span class="s">""</span><span class="o">;</span>
<span class="k">for</span> <span class="o">(</span><span class="kt">int</span> <span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="o">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">my_string</span><span class="o">.</span><span class="na">length</span><span class="o">();</span> <span class="n">i</span><span class="o">++){</span>
    <span class="n">answer</span> <span class="o">+=</span> <span class="n">my_string</span><span class="o">.</span><span class="na">charAt</span><span class="o">(</span><span class="n">my_string</span><span class="o">.</span><span class="na">length</span><span class="o">()-(</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="o">));</span>
<span class="o">}</span>
</code></pre></div></div>

<ul>
  <li>String은 []로 접근할 수 없고, ~번째 글자는 charAt() 메서드를 이용함</li>
  <li>length도 멤버가 아닌 메서드로 호출해야함</li>
  <li>StringBuilder를 이용하면 append, reverse가 쉬움</li>
</ul>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">java.util.*</span><span class="o">;</span>

<span class="nc">StringBuilder</span><span class="o">(</span><span class="n">myString</span><span class="o">).</span><span class="na">reverse</span><span class="o">().</span><span class="na">toString</span><span class="o">();</span>
</code></pre></div></div>]]></content><author><name>Juyoung Hong</name><email>hjy_stat@naver.com</email></author><category term="coding" /><category term="java" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">오라클 쿠버네티스 CI,CD 배포환경 구성하기-2</title><link href="https://juyoung-hong.github.io/infra/setcicd2/" rel="alternate" type="text/html" title="오라클 쿠버네티스 CI,CD 배포환경 구성하기-2" /><published>2026-06-03T00:00:00+09:00</published><updated>2026-06-03T00:00:00+09:00</updated><id>https://juyoung-hong.github.io/infra/setcicd2</id><content type="html" xml:base="https://juyoung-hong.github.io/infra/setcicd2/"><![CDATA[<p><br /></p>

<h1 id="오라클-쿠버네티스-배포-환경-구성하기-2">오라클 쿠버네티스 배포 환경 구성하기-2</h1>

<p><br /></p>

<p>오늘은 지난 글에 이어서 쿠버네티스 클러스터에 구성했던 어플리케이션을 배포하고, Jenkins와 연결하는 구성을 해보겠습니다.</p>

<p>오라클 쿠버네티스 클러스터가 만들어져 있어야하며, Jenkins 설정도 완료되어 있음을 가정하겠습니다.</p>

<ul>
  <li>오라클 클라우드에 무료 관리형 쿠버네티스 서버 구성하기: <a href="https://juyoung-hong.github.io/infra/ocioke/">링크</a></li>
  <li>간단한 React 앱 구성 후 OKE에 배포하기: <a href="https://juyoung-hong.github.io/devops/github_organization/">링크</a></li>
  <li>오라클 쿠버네티스 CI,CD 배포환경 구성하기-1: <a href="https://juyoung-hong.github.io/infra/setcicd/">링크</a></li>
</ul>

<p><br /></p>

<h1 id="oci-native-ingress-controller-설치">OCI native Ingress Controller 설치</h1>

<p><br /></p>

<p>생성된 OKE에 여러개의 서비스를 배포하고, 1개의 로드밸런서에서 경로에 따라 올바른 파드로 연결하는 등의 기능을 위해 Ingress Controller를 설정해야합니다.</p>

<p>많이 사용하는 Nginx Ingress Controller의 경우, 2026년 3월 지원이 종료되어 더이상 버그 패치, 보안 패치 등이 지원되지 않으므로 OCI 의 Ingress Controller를 설치해보겠습니다.</p>

<p><br /></p>

<h2 id="pre-requirements-확인">Pre-requirements 확인</h2>

<p><br /></p>

<p><a href="https://github.com/oracle/oci-native-ingress-controller">OCI native ingress controller</a> github를 보면 아래의 조건을 만족해야 OCI Ingress Controller를 설치할 수 있습니다.</p>

<ul>
  <li><strong>지원 K8s 버전:</strong> 1.27 ~ 1.32</li>
  <li><strong>네트워크 플러그인(CNI)</strong>: Native Pod Networking(NPN) 또는 Flannel CNI 사용 환경</li>
</ul>

<p>우리 구성환경은 K8s 1.32 버전을 사용하며, Native Pod Networking을 사용하고 있으므로 사전 요구사항을 만족하며 다음 설정을 확인합니다.</p>

<p><br /></p>

<h2 id="cert-manager-설치">Cert Manager 설치</h2>

<p><br /></p>

<p>인그레스 컨트롤러가 사용하는 웹훅(Webhook)의 TLS 인증서 관리를 위해 cert-manager가 배포되어 있어야 합니다.</p>

<p>OCI CLI가 설치되어 있고, OKE와 연결된 환경에서 아래의 명령어로 Cert Manager를 배포합니다.</p>

<p>저는 앞으로 배포를 담당할 CI/CD VM에서 실행하였습니다.</p>

<p>아래 명령을 실행하는데 있어, CICD VM =&gt; OKE Cluster 구간의 방화벽 설정으로 인해 오류가 발생하여 KUBERNETES_APIENDPOINTS_SecurityList 방화벽 규칙에 Ingress Rule로 6443 포트 TCP 통신에 대한 Ingress Rule을 추가하고 진행하였습니다.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>kubectl apply <span class="nt">-f</span> https://github.com/jetstack/cert-manager/releases/latest/download/cert-manager.yaml
kubectl get pods <span class="nt">-n</span> cert-manager <span class="c"># 설치 후 POD가 정상 동작하는지 확인</span>
</code></pre></div></div>

<p><img src="/assets/images/2026-06-03-setcicd2/install_certmanager.jpeg" alt="install_certmanager" /></p>

<p>위 이미지와 같이 설치 및 POD가 정상적으로 동작함을 확인한 뒤 다음으로 넘어갑니다.</p>

<p><br /></p>

<h2 id="iam-정책-추가">IAM 정책 추가</h2>

<p><br /></p>

<p>OCI 콘솔에서 OKE 워커 노드(또는 동적 그룹/사용자)가 로드밸런서 및 네트워크 자원을 관리할 수 있도록 다음 정책을 추가합니다.</p>

<p class="notice--info"><strong>삽질 후기:</strong> <br />
Dynamic Group 생성 및 Policy 추가는 아래와 같이 따라하면 되지만, 저는 결국엔 아래 방법으로 해결되지 않아, User 방식으로 수정하여 적용하였습니다. <br />
같은 방법으로 적용을 원하시면 아래 Dynamic Group, Policy 관련 섹션은 건너뛰셔도 됩니다. <br /></p>

<p><br /></p>

<h3 id="dynamic-group-생성">Dynamic Group 생성</h3>

<p><br /></p>

<p><img src="/assets/images/2026-06-03-setcicd2/set_dynamic_group1.jpeg" alt="set_dynamic_group1" /></p>

<p>위 이미지와 같이 OCI 콘솔에서 Identity &amp; Security &gt; Domains 메뉴를 찾아 들어간 뒤, 내 도메인 리소스가 위치하는 컴파트먼트로 변경하여 도메인 리소스 상세 페이지로 이동합니다.</p>

<p><img src="/assets/images/2026-06-03-setcicd2/set_dynamic_group2.jpeg" alt="set_dynamic_group2" /></p>

<p>이후 Dynamic Groups 탭을 클릭한 뒤, Create Dynamic groups 버튼을 클릭하여 신규 Dynamic group을 생성합니다.</p>

<p><img src="/assets/images/2026-06-03-setcicd2/set_dynamic_group3.jpeg" alt="set_dynamic_group3" /></p>

<p>생성할 다이나믹 그룹의 이름과 설명을 입력한 뒤, 설정할 Rule을 아래의 양식으로 입력합니다.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>instance.compartment.id <span class="o">=</span> <span class="s1">'ocid1.compartment.oc1..내컴파트먼트OCID'</span>
</code></pre></div></div>

<p>적용할 compartment의 OCID는 OCI 콘솔의 Identity &amp; Security &gt; Compartments 메뉴에서 compartment를 선택하면 확인할 수 있습니다.</p>

<p><br /></p>

<h3 id="policy-생성">Policy 생성</h3>

<p><br /></p>

<p><img src="/assets/images/2026-06-03-setcicd2/create_policy.jpeg" alt="create_policy" /></p>

<p>이번에는 OCI 콘솔에서 Identity &amp; Security &gt; Policies 메뉴를 찾아 들어간 뒤, 생성할 compartment를 선택한 뒤 Create Policy로 적용할 정책을 생성합니다.</p>

<p><img src="/assets/images/2026-06-03-setcicd2/create_policy2.jpeg" alt="create_policy2" /></p>

<p>마찬가지로 Policy 이름과 설명을 입력한 뒤, Show manual editor 버튼을 클릭하고, 본인의 리소스에 맞게 아래의 텍스트를 수정해서 정책을 생성합니다.</p>

<p>subject에서는 생성한 dynamic group의 이름을 입력하고, compartment-id는 정책을 적용할 compartment의 이름을 입력합니다.</p>

<p>이미지상에서는 콘솔에서 prd-mlplatform compartment를 선택하였으나, 적용할 compartment보다 상위 compartment를 선택한 상태에서 정책 생성이 되어야 하기에 root로 변경 후 생성하였습니다.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Allow dynamic-group &lt;subject&gt; to manage load-balancers <span class="k">in </span>compartment <span class="nb">id</span> &lt;compartment-id&gt;
Allow dynamic-group &lt;subject&gt; to use virtual-network-family <span class="k">in </span>compartment <span class="nb">id</span> &lt;compartment-id&gt;
Allow dynamic-group &lt;subject&gt; to manage cabundles <span class="k">in </span>compartment <span class="nb">id</span> &lt;compartment-id&gt;
Allow dynamic-group &lt;subject&gt; to manage cabundle-associations <span class="k">in </span>compartment <span class="nb">id</span> &lt;compartment-id&gt;
Allow dynamic-group &lt;subject&gt; to manage leaf-certificates <span class="k">in </span>compartment <span class="nb">id</span> &lt;compartment-id&gt;
Allow dynamic-group &lt;subject&gt; to manage leaf-certificates-versions <span class="k">in </span>compartment <span class="nb">id</span> &lt;compartment-id&gt;
Allow dynamic-group &lt;subject&gt; to <span class="nb">read </span>leaf-certificate-bundles <span class="k">in </span>compartment <span class="nb">id</span> &lt;compartment-id&gt;
Allow dynamic-group &lt;subject&gt; to manage certificate-associations <span class="k">in </span>compartment <span class="nb">id</span> &lt;compartment-id&gt;
Allow dynamic-group &lt;subject&gt; to <span class="nb">read </span>certificate-authorities <span class="k">in </span>compartment <span class="nb">id</span> &lt;compartment-id&gt;
Allow dynamic-group &lt;subject&gt; to manage certificate-authority-associations <span class="k">in </span>compartment <span class="nb">id</span> &lt;compartment-id&gt;
Allow dynamic-group &lt;subject&gt; to <span class="nb">read </span>certificate-authority-bundles <span class="k">in </span>compartment <span class="nb">id</span> &lt;compartment-id&gt;
ALLOW dynamic-group &lt;subject&gt; to <span class="nb">read </span>public-ips <span class="k">in </span>tenancy
ALLOW dynamic-group &lt;subject&gt; to manage floating-ips <span class="k">in </span>tenancy
Allow dynamic-group &lt;subject&gt; to manage waf-family <span class="k">in </span>compartment <span class="nb">id</span> &lt;compartment-id&gt;
Allow dynamic-group &lt;subject&gt; to <span class="nb">read </span>cluster-family <span class="k">in </span>compartment <span class="nb">id</span> &lt;compartment-id&gt;
Allow dynamic-group &lt;subject&gt; to use tag-namespaces <span class="k">in </span>tenancy
</code></pre></div></div>

<p><br /></p>

<h2 id="oci-ingress-controller-설치">OCI Ingress Controller 설치</h2>

<p><br /></p>

<h3 id="helm-설치">Helm 설치</h3>

<p><br /></p>

<p>이제 OCI Ingress Controller를 설치하기 위해 먼저 Helm을 설치합니다.</p>

<p><a href="https://helm.sh/docs/intro/install/">Helm 공식 문서</a>에 있는 Ubuntu 부분을 찾아 아래 명령어를 수행하여 CICD 장비에 Helm을 설치합니다.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">HELM_BUILDKITE_APT_KEY_ID</span><span class="o">=</span><span class="s2">"DDF78C3E6EBB2D2CC223C95C62BA89D07698DBC6"</span>

<span class="nb">sudo </span>apt-get <span class="nb">install </span>curl gpg apt-transport-https <span class="nt">--yes</span>

curl <span class="nt">-fsSL</span> https://packages.buildkite.com/helm-linux/helm-debian/gpgkey <span class="o">&gt;</span> <span class="s2">"</span><span class="k">${</span><span class="nv">TMPDIR</span><span class="k">:-</span><span class="p">/tmp</span><span class="k">}</span><span class="s2">/helm.gpg"</span>

<span class="c"># Ensure that the key ID matches to prevent a repository compromise from establishing an attacker controlled key</span>
<span class="k">if</span> <span class="o">[</span> <span class="s2">"</span><span class="si">$(</span>gpg <span class="nt">--show-keys</span> <span class="nt">--with-colons</span> <span class="s2">"</span><span class="k">${</span><span class="nv">TMPDIR</span><span class="k">:-</span><span class="p">/tmp</span><span class="k">}</span><span class="s2">/helm.gpg"</span> | <span class="nb">awk</span> <span class="nt">-F</span>: <span class="s1">'$1 == "fpr" {print $10}'</span> | <span class="nb">head</span> <span class="nt">-n</span> 1<span class="si">)</span><span class="s2">"</span> <span class="o">!=</span> <span class="s2">"</span><span class="k">${</span><span class="nv">HELM_BUILDKITE_APT_KEY_ID</span><span class="k">}</span><span class="s2">"</span> <span class="o">]</span><span class="p">;</span> <span class="k">then </span><span class="nb">echo</span> <span class="s2">"ERROR: Unexpected Helm APT key ID: potential key compromise"</span><span class="p">;</span> <span class="nb">exit </span>1<span class="p">;</span> <span class="k">fi

</span><span class="nb">cat</span> <span class="s2">"</span><span class="k">${</span><span class="nv">TMPDIR</span><span class="k">:-</span><span class="p">/tmp</span><span class="k">}</span><span class="s2">/helm.gpg"</span> | gpg <span class="nt">--dearmor</span> | <span class="nb">sudo tee</span> /usr/share/keyrings/helm.gpg <span class="o">&gt;</span> /dev/null
<span class="nb">echo</span> <span class="s2">"deb [signed-by=/usr/share/keyrings/helm.gpg] https://packages.buildkite.com/helm-linux/helm-debian/any/ any main"</span> | <span class="nb">sudo tee</span> /etc/apt/sources.list.d/helm-stable-debian.list

<span class="nb">sudo </span>apt-get update
<span class="nb">sudo </span>apt-get <span class="nb">install </span>helm
</code></pre></div></div>

<p><br /></p>

<h3 id="secret-생성">secret 생성</h3>

<p><br /></p>

<p>이제 oci-native Ingress Controller를 클론해 옵니다.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git clone https://github.com/oracle/oci-native-ingress-controller.git
<span class="nb">cd </span>oci-native-ingress-controller
</code></pre></div></div>

<p class="notice--info"><strong>삽질 후기:</strong> <br />
위에서 설정한 dynamic group, policy가 맞다면 instance 방식으로 정상 동작해야하지만 계속하여 Auth 관련 오류가 발생하였습니다. <br />
여러번의 삽질 끝에 저는 user 기반으로 인증을 적용하였습니다. <br /></p>

<p>user 기반으로 OCI API에 access 할 수 있도록 oci-native-ingress-controller 폴더 하위에 user-auth-config.yaml 파일을 아래와 같이 작성하였습니다.</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#</span>
<span class="c1"># OCI Native Ingress Controller</span>
<span class="c1">#</span>
<span class="c1"># Copyright (c) 2023 Oracle America, Inc. and its affiliates.</span>
<span class="c1"># Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/</span>
<span class="c1">#</span>
<span class="na">auth</span><span class="pi">:</span>
  <span class="na">region</span><span class="pi">:</span> <span class="s">ap-chuncheon-1</span>
  <span class="na">passphrase</span><span class="pi">:</span> 
  <span class="na">user</span><span class="pi">:</span> <span class="s">ocid1.user.oc1..aaaaaaaa_example</span> <span class="c1"># oci 콘솔 확인</span>
  <span class="na">fingerprint</span><span class="pi">:</span> <span class="s">67:d9:74:4b:21:example</span> <span class="c1"># oci 콘솔 확인 (User - API Key 탭)</span>
  <span class="na">tenancy</span><span class="pi">:</span> <span class="s">ocid1.tenancy.oc1..aaaaaaaa_example</span> <span class="c1"># oci 콘솔 확인</span>
</code></pre></div></div>

<p>이후 아래의 명령어로 secret을 생성해줍니다.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>kubectl create namespace native-ingress-controller-system
kubectl create secret generic oci-config <span class="se">\</span>
         <span class="nt">--from-file</span><span class="o">=</span><span class="nv">config</span><span class="o">=</span>user-auth-config.yaml <span class="se">\</span>
         <span class="nt">--from-file</span><span class="o">=</span>private-key<span class="o">=</span>/home/ubuntu/.oci/oci_api_key.pem <span class="se">\ </span><span class="c"># 이전에 발급해둔 oci 계정의 api key</span>
         <span class="nt">--namespace</span> native-ingress-controller-system
</code></pre></div></div>

<h3 id="valuesyaml-파일-수정">values.yaml 파일 수정</h3>

<p><br /></p>

<p>이제 oci-native-ingress-controller/helm/oci-native-ingress-controller/values.yaml 파일에서 각 ocid를 찾아 입력합니다. subnet의 경우, LB를 컨트롤 할 수 있도록 LB가 위치할 LoadBalancer Subnet의 OCID를 입력하였습니다.</p>

<p>위에서 user 정보로 secret을 만들었으니, authType의 값도 instance에서 user로 변경해줍니다.</p>

<p><img src="/assets/images/2026-06-03-setcicd2/edit_values.jpeg" alt="edit_values" /></p>

<p>values.yaml 파일이 작성 완료된 후에는 아래 명령어로 values.yaml 파일과 oci-config secret 기반으로 ingress controller를 설치합니다.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>helm <span class="nb">install </span>oci-native-ingress-controller helm/oci-native-ingress-controller
</code></pre></div></div>

<p>Ingress Controller 설치 과정에서 정말 애먹었는데, Dynamic Group 생성 후 Policy 생성까지만 하면 <code class="language-plaintext highlighter-rouge">Request Endpoint: GET https://containerengine.ap-chuncheon-1.oci.oraclecloud.com/20180222/clusters/ocid1.cluster.oc1.ap-chuncheon-1.aaaa...</code> 에러 메시지와 함께 정상 동작하지 않습니다.</p>

<p>cluster-family에 대한 manage 권한을 줘도 마찬가지였고, 결국에는 authType을 instance가 아닌 user로 줘야 정상 동작하게 되었습니다.</p>

<p>같은 이슈가 있으신 분들은 authType user 기준으로 secret 생성 후 values.yaml 파일을 작성하고 helm 으로 설치하시기를 바랍니다.</p>

<p>정상 설치가 되면 아래 명령어로 ingress contoller가 정상 running 하는 것을 확인할 수 있습니다.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>kubectl get pods <span class="nt">-n</span> native-ingress-controller-system <span class="nt">-o</span> wide <span class="nt">-w</span>
</code></pre></div></div>

<p><br /></p>

<h2 id="oci-ingress-controller-설정">OCI Ingress Controller 설정</h2>

<p><br /></p>

<p>우선 Ingress Controller를 설정하기 전에 기존에 배포해뒀던 nginx 관련 리소스들을 삭제합니다.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>kubectl delete deployment nginx-deployment <span class="nt">-n</span> default
kubectl delete service nginx-service <span class="nt">-n</span> default
kubectl get deployments,services,pods,ingress
</code></pre></div></div>

<p>그리고 1개의 LB를 공용으로 사용하며, 여러개의 namespace로 나뉘어진 서비스들에 라우팅 해줄 수 있도록 아래와 같이 native-ic-ingress-params.yaml 파일을 작성합니다.</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#</span>
<span class="c1"># OCI Native Ingress Controller</span>
<span class="c1">#</span>
<span class="c1"># Copyright (c) 2023 Oracle America, Inc. and its affiliates.</span>
<span class="c1"># Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/</span>
<span class="c1">#</span>
<span class="na">apiVersion</span><span class="pi">:</span> <span class="s2">"</span><span class="s">ingress.oraclecloud.com/v1beta1"</span>
<span class="na">kind</span><span class="pi">:</span> <span class="s">IngressClassParameters</span>
<span class="na">metadata</span><span class="pi">:</span>
  <span class="na">name</span><span class="pi">:</span> <span class="s">native-ic-ingress-params</span>
  <span class="na">namespace</span><span class="pi">:</span> <span class="s">native-ingress-controller-system</span>
<span class="na">spec</span><span class="pi">:</span>
  <span class="na">compartmentId</span><span class="pi">:</span> <span class="s2">"</span><span class="s">LB를</span><span class="nv"> </span><span class="s">배포할</span><span class="nv"> </span><span class="s">compartment의</span><span class="nv"> </span><span class="s">ocid"</span>
  <span class="na">subnetId</span><span class="pi">:</span> <span class="s2">"</span><span class="s">LB를</span><span class="nv"> </span><span class="s">배포할</span><span class="nv"> </span><span class="s">subnet의</span><span class="nv"> </span><span class="s">ocid"</span>
  <span class="na">loadBalancerName</span><span class="pi">:</span> <span class="s2">"</span><span class="s">native-ingress-controller-lb"</span>
  <span class="na">isPrivate</span><span class="pi">:</span> <span class="no">false</span>
  <span class="na">maxBandwidthMbps</span><span class="pi">:</span> <span class="m">10</span>
  <span class="na">minBandwidthMbps</span><span class="pi">:</span> <span class="m">10</span>
</code></pre></div></div>

<p>이제 작성된 native-ic-ingress-params.yaml 파일을 적용합니다.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>kubectl apply <span class="nt">-f</span> native-ic-ingress-params.yaml
kubectl get ingressclassparameters <span class="nt">-n</span> native-ingress-controller-system
</code></pre></div></div>

<p>이후 아래와 같이 native-ic-ingress-class.yaml 파일을 작성합니다.</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#</span>
<span class="c1"># OCI Native Ingress Controller</span>
<span class="c1">#</span>
<span class="c1"># Copyright (c) 2023 Oracle America, Inc. and its affiliates.</span>
<span class="c1"># Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/</span>
<span class="c1">#</span>
<span class="na">apiVersion</span><span class="pi">:</span> <span class="s">networking.k8s.io/v1</span>
<span class="na">kind</span><span class="pi">:</span> <span class="s">IngressClass</span>
<span class="na">metadata</span><span class="pi">:</span>
  <span class="na">name</span><span class="pi">:</span> <span class="s">native-ic-ingress-class</span>
  <span class="na">annotations</span><span class="pi">:</span>
    <span class="na">ingressclass.kubernetes.io/is-default-class</span><span class="pi">:</span> <span class="s2">"</span><span class="s">true"</span>
<span class="na">spec</span><span class="pi">:</span>
  <span class="na">controller</span><span class="pi">:</span> <span class="s">oci.oraclecloud.com/native-ingress-controller</span>
  <span class="na">parameters</span><span class="pi">:</span>
    <span class="na">scope</span><span class="pi">:</span> <span class="s">Namespace</span>
    <span class="na">namespace</span><span class="pi">:</span> <span class="s">native-ingress-controller-system</span>
    <span class="na">apiGroup</span><span class="pi">:</span> <span class="s">ingress.oraclecloud.com</span>
    <span class="na">kind</span><span class="pi">:</span> <span class="s">ingressclassparameters</span>
    <span class="na">name</span><span class="pi">:</span> <span class="s">native-ic-ingress-params</span>
</code></pre></div></div>

<p>아래 명령어로 ingress class도 생성합니다.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>kubectl apply <span class="nt">-f</span> native-ic-ingress-class.yaml
kubectl get ingressclass <span class="nt">-n</span> native-ingress-controller-system
</code></pre></div></div>

<p><br /></p>

<h1 id="front-앱-수동-배포">front 앱 수동 배포</h1>

<p><br /></p>

<p>이제 ingress 설정이 마무리되었으니 지난번에 만들어둔 react 앱을 수동으로 배포해봅니다.</p>

<p><br /></p>

<h2 id="oci-container-registry-생성">OCI Container Registry 생성</h2>

<p><br /></p>

<p><img src="/assets/images/2026-06-03-setcicd2/create_container_registry.jpeg" alt="create_container_registry" /></p>

<p>OCI 콘솔에서 Developer Services &gt; Container Registry 메뉴에서 Create repository 버튼을 클릭하여 Container Registry를 생성합니다.</p>

<p><img src="/assets/images/2026-06-03-setcicd2/create_container_registry2.jpeg" alt="create_container_registry2" /></p>

<p>Repository 명은 GitHub의 Organization / Repo 명을 따라 작명해주었고, Private Registry로 생성해주었습니다.</p>

<p><br /></p>

<h3 id="인증-토큰-생성">인증 토큰 생성</h3>

<p><br /></p>

<p>생성된 Container Registry에 이미지를 업로드할 수 있도록 인증 토큰에 대해 발급이 필요합니다.</p>

<p>OCI 콘솔의 My Profile 화면의 Tokens and keys 탭에서 Auth Token 을 찾아, Generate token을 클릭하여 생성해줍니다.</p>

<p><img src="/assets/images/2026-06-03-setcicd2/create_container_registry2.jpeg" alt="create_container_registry2" /></p>

<p>description을 저장한채로 생성 버튼을 클릭하면 나오는 key를 잃어버리지 않게 잘 보관합니다.</p>

<p>이제 docker cli로 컨테이너 레지스트리에 로그인합니다.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker login yny.ocir.io
</code></pre></div></div>

<p>춘천지역의 코드가 yny이므로 위 명령어로 생성되었고, 다른 지역이라면 지역코드를 찾아 바꿔주어야 합니다.</p>

<p>로그인시에 사용자 ID는 <code class="language-plaintext highlighter-rouge">테넌시ID/username</code>로 입력해야하며, 테넌시 ID는 <code class="language-plaintext highlighter-rouge">oci os ns get</code>으로 확인할 수 있고, username은 OCI 콘솔의 MyProfile에서 확인할 수 있습니다.</p>

<p>정상적으로 Login Succeeded 로그를 확인한 후에는 이미지를 빌드합니다.</p>

<p><br /></p>

<h2 id="docker-이미지-준비">Docker 이미지 준비</h2>

<p><br /></p>

<p>repo 안에 아래와 같이 docker file을 생성해서 원격 저장소에 push 해줍니다.</p>

<div class="language-Dockerfile highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># 1단계: Node 빌드 환경 (플랫폼 명시 가능하도록 구조화)</span>
<span class="k">FROM</span><span class="w"> </span><span class="s">--platform=$BUILDPLATFORM node:20-alpine</span><span class="w"> </span><span class="k">AS</span><span class="w"> </span><span class="s">build</span>
<span class="k">WORKDIR</span><span class="s"> /app</span>

<span class="k">COPY</span><span class="s"> package*.json ./</span>
<span class="c"># ARM 네임스페이스 컴파일 속도 향상 및 불필요한 캐시 제거</span>
<span class="k">RUN </span>npm ci <span class="nt">--quiet</span>

<span class="k">COPY</span><span class="s"> . .</span>
<span class="k">RUN </span>npm run build

<span class="c"># 2단계: 호스트와 아키텍처가 일치하는 가벼운 Nginx 아키텍처로 정적 파일 이관</span>
<span class="k">FROM</span><span class="s"> --platform=$TARGETPLATFORM nginx:alpine</span>
<span class="k">RUN </span><span class="nb">rm</span> <span class="nt">-rf</span> /etc/nginx/conf.d/default.conf
<span class="k">RUN </span><span class="nb">echo</span> <span class="s1">'server { listen 80; location / { root /usr/share/nginx/html; index index.html index.htm; try_files $uri $uri/ /index.html; } }'</span> <span class="o">&gt;</span> /etc/nginx/conf.d/default.conf

<span class="k">COPY</span><span class="s"> --from=build /app/dist /usr/share/nginx/html</span>
<span class="k">EXPOSE</span><span class="s"> 80</span>
<span class="k">CMD</span><span class="s"> ["nginx", "-g", "daemon off;"]</span>
</code></pre></div></div>

<p>CICD VM은 x86기반 아키텍처의 장비이지만, OKE는 ARM 기반 아키텍처 장비로 만들어둔 관계로 멀티 아키텍처용 빌더를 구성한 뒤 docker file을 빌드하여 이미지를 만들어줍니다.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># 빌드킷(BuildKit) 핵심 이미지 미리 다운로드</span>
docker pull moby/buildkit:buildx-stable-1

<span class="c"># 1. 멀티 아키텍처용 빌더 생성</span>
docker buildx create <span class="nt">--name</span> mybuilder <span class="nt">--use</span>

<span class="c"># 2. 빌더 기동 및 상태 확인</span>
docker buildx inspect <span class="nt">--bootstrap</span>

<span class="c"># 3. docker 이미지 빌드</span>
docker buildx build <span class="se">\</span>
  <span class="nt">--platform</span> linux/arm64 <span class="se">\</span>
  <span class="nt">-t</span> mlplatform/fe-www:v1.0.0 <span class="se">\</span>
  <span class="nt">--load</span> <span class="nb">.</span>

<span class="c"># 4. 빌드된 이미지 확인</span>
docker images

<span class="c"># 5. docker tag 변경</span>
docker tag mlplatform/fe-www:v1.0.0 yny.ocir.io/&lt;테넌시명&gt;/mlplatform/fe-www:v1.0.0

<span class="c"># 6. OCIR에 push</span>
docker push yny.ocir.io/&lt;테넌시명&gt;/mlplatform/fe-www:v1.0.0
</code></pre></div></div>

<p><img src="/assets/images/2026-06-03-setcicd2/create_container_registry2.jpeg" alt="create_container_registry2" /></p>

<p>push가 잘 완료된 이후에는 OCI 콘솔에서 image를 확인할 수 있습니다.</p>

<p><br /></p>

<h2 id="쿠버네티스-배포">쿠버네티스 배포</h2>

<p><br /></p>

<h3 id="docker-registry-secret-생성">docker registry secret 생성</h3>

<p><br /></p>

<p>이제 위에서 테스트한 내용을 바탕으로 OKE 클러스터에 OCR에 접근할 수 있는 정보를 secret으로 만들어 저장합니다.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>kubectl create secret docker-registry ocirsecret <span class="nt">--docker-server</span><span class="o">=</span>yny.ocir.io <span class="nt">--docker-username</span><span class="o">=</span><span class="s1">'테넌시id/username'</span> <span class="nt">--docker-password</span><span class="o">=</span><span class="s1">'token'</span>
kubectl get secrets
</code></pre></div></div>

<p><br /></p>

<h3 id="ingress-yaml-작성-및-적용">ingress yaml 작성 및 적용</h3>

<p><br /></p>

<p>정상적으로 secret이 만들어졌으니, 클러스터 배포를 위해 namespace를 생성하고 적용합니다.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>kubectl create namespace mlplatform
kubectl create secret docker-registry ocirsecret <span class="nt">--docker-server</span><span class="o">=</span>yny.ocir.io <span class="nt">--docker-username</span><span class="o">=</span><span class="s1">'테넌시id/username'</span> <span class="nt">--docker-password</span><span class="o">=</span><span class="s1">'token'</span> <span class="nt">-n</span> mlplatform <span class="c"># 새로 생성한 namespace에도 secret 생성</span>
</code></pre></div></div>

<p>이후 아래와 같이 fe-www 서비스를 배포하기 위한 yaml 파일을 작성합니다.</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># 1. 배포 (Deployment)</span>
<span class="na">apiVersion</span><span class="pi">:</span> <span class="s">apps/v1</span>
<span class="na">kind</span><span class="pi">:</span> <span class="s">Deployment</span>
<span class="na">metadata</span><span class="pi">:</span>
  <span class="na">name</span><span class="pi">:</span> <span class="s">fe-www-deployment</span>
  <span class="na">namespace</span><span class="pi">:</span> <span class="s">mlplatform</span>
<span class="na">spec</span><span class="pi">:</span>
  <span class="na">replicas</span><span class="pi">:</span> <span class="m">1</span>
  <span class="na">selector</span><span class="pi">:</span>
    <span class="na">matchLabels</span><span class="pi">:</span>
      <span class="na">app</span><span class="pi">:</span> <span class="s">fe-www</span>
  <span class="na">template</span><span class="pi">:</span>
    <span class="na">metadata</span><span class="pi">:</span>
      <span class="na">labels</span><span class="pi">:</span>
        <span class="na">app</span><span class="pi">:</span> <span class="s">fe-www</span>
    <span class="na">spec</span><span class="pi">:</span>
      <span class="na">containers</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">fe-www-container</span>
        <span class="na">image</span><span class="pi">:</span> <span class="s">yny.ocir.io/axqyrowq4jay/mlplatform/fe-www:v1.0.0</span>
        <span class="na">ports</span><span class="pi">:</span>
        <span class="pi">-</span> <span class="na">containerPort</span><span class="pi">:</span> <span class="m">80</span>
      <span class="na">imagePullSecrets</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">ocir-secret</span> <span class="c1"># 아까 만든 시크릿 이름</span>
<span class="nn">---</span>
<span class="na">apiVersion</span><span class="pi">:</span> <span class="s">v1</span>
<span class="na">kind</span><span class="pi">:</span> <span class="s">Service</span>
<span class="na">metadata</span><span class="pi">:</span>
  <span class="na">name</span><span class="pi">:</span> <span class="s">fe-www-svc</span>
  <span class="na">namespace</span><span class="pi">:</span> <span class="s">mlplatform</span>
<span class="na">spec</span><span class="pi">:</span>
  <span class="na">selector</span><span class="pi">:</span>
    <span class="na">app</span><span class="pi">:</span> <span class="s">fe-www</span>  <span class="c1"># 이 부분이 Deployment의 matchLabels와 일치해야 합니다!</span>
  <span class="na">ports</span><span class="pi">:</span>
    <span class="pi">-</span> <span class="na">protocol</span><span class="pi">:</span> <span class="s">TCP</span>
      <span class="na">port</span><span class="pi">:</span> <span class="m">80</span>      <span class="c1"># 인그레스에서 참조할 포트</span>
      <span class="na">targetPort</span><span class="pi">:</span> <span class="m">80</span> <span class="c1"># 컨테이너 내부 포트</span>
</code></pre></div></div>

<p>위에서 작성한 yaml 파일을 아래 명령어로 작성하여, deployment와 service를 생성합니다.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>kubectl apply <span class="nt">-f</span> fe-www.yaml
kubectl get deployments,services,pods <span class="nt">-n</span> mlplatform
</code></pre></div></div>

<p>잘 생성 된 것을 확인한 이후에는 마지막으로 native-ic-ingress-path-basic.yaml 파일을 작성하여 lb와 연결해줍니다.</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">apiVersion</span><span class="pi">:</span> <span class="s">networking.k8s.io/v1</span>
<span class="na">kind</span><span class="pi">:</span> <span class="s">Ingress</span>
<span class="na">metadata</span><span class="pi">:</span>
  <span class="na">name</span><span class="pi">:</span> <span class="s">native-ic-ingress-path-basic</span>
  <span class="na">namespace</span><span class="pi">:</span> <span class="s">mlplatform</span>
<span class="na">spec</span><span class="pi">:</span>
  <span class="na">ingressClassName</span><span class="pi">:</span> <span class="s">native-ic-ingress-class</span>
  <span class="na">rules</span><span class="pi">:</span>
  <span class="pi">-</span> <span class="na">http</span><span class="pi">:</span>
      <span class="na">paths</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="na">path</span><span class="pi">:</span> <span class="s">/</span>
        <span class="na">pathType</span><span class="pi">:</span> <span class="s">Prefix</span>
        <span class="na">backend</span><span class="pi">:</span>
          <span class="na">service</span><span class="pi">:</span>
            <span class="na">name</span><span class="pi">:</span> <span class="s">fe-www-svc</span>
            <span class="na">port</span><span class="pi">:</span>
              <span class="na">number</span><span class="pi">:</span> <span class="m">80</span>
</code></pre></div></div>

<p>위 파일을 저장한 후 아래 명령어로 ingress 리소스를 생성해줍니다.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>kubectl apply <span class="nt">-f</span> native-ic-ingress-path-basic.yaml
</code></pre></div></div>

<h3 id="ingress-리소스-요약">ingress 리소스 요약</h3>

<p>저는 무료로 제공되는 리소스 내에서 여러개의 프로젝트를 진행할 수 있도록 ingress를 도입하였기에 아래와 같은 구조로 리소스를 위치했습니다.</p>

<p>이제 신규로 생성되는 네임스페이스가 있다면 마지막의 native-ic-ingress-path-basic.yaml 파일만 작성하여, 각 네임스페이스에 두고, 그 외 ingress 관련 리소스들은 native-ingress-controller-system 네임스페이스에서 관리됩니다.</p>

<p><img src="/assets/images/2026-06-03-setcicd2/ingress_structure.jpeg" alt="ingress_structure" /></p>

<h3 id="배포-확인">배포 확인</h3>

<p>위 내용이 모두 완료되었다면, yaml 파일에 적용된 규칙을 따르는 Load Balancer가 OCI 콘솔에 생성되어 있는 것을 확인할 수 있습니다.</p>

<p>해당 LB의 Public IP 주소로 접근 하면, 미리 만들어 놓았던 Vite + React의 메인 페이지를 확인할 수 있습니다.</p>

<p><img src="/assets/images/2026-06-03-setcicd2/created_lb.jpeg" alt="created_lb" /></p>

<p><img src="/assets/images/2026-06-03-setcicd2/deployed_app.jpeg" alt="deployed_app" /></p>

<p>이제 수동 배포는 정상적으로 수행하였고, 앱도 잘 올라가 있는 것을 확인하였으니, 다음 포스트에서는 jenkins가 배포 내용을 자동 식별해서 배포할 수 있도록 설정해보겠습니다.</p>]]></content><author><name>Juyoung Hong</name><email>hjy_stat@naver.com</email></author><category term="infra" /><category term="oracle-cloud" /><category term="jenkins" /><category term="CI" /><category term="CD" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">오라클 쿠버네티스 CI,CD 배포환경 구성하기-1</title><link href="https://juyoung-hong.github.io/infra/setcicd/" rel="alternate" type="text/html" title="오라클 쿠버네티스 CI,CD 배포환경 구성하기-1" /><published>2026-05-05T00:00:00+09:00</published><updated>2026-05-05T00:00:00+09:00</updated><id>https://juyoung-hong.github.io/infra/setcicd</id><content type="html" xml:base="https://juyoung-hong.github.io/infra/setcicd/"><![CDATA[<p><br /></p>

<h1 id="오라클-쿠버네티스-배포-환경-구성하기-1">오라클 쿠버네티스 배포 환경 구성하기-1</h1>

<p><br /></p>

<p>오늘은 지난 글에 이어서 생성한 쿠버네티스 클러스터에 개발 내용을 자동으로 배포할 수 있도록 Jenkins라는 도구를 통해 CI/CD 구성을 해보겠습니다.</p>

<p>오라클 쿠버네티스 클러스터가 만들어져 있는 상태여야 하므로 이전 글과 함께 봐주시면 감사하겠습니다.</p>

<ul>
  <li>오라클 클라우드에 무료 관리형 쿠버네티스 서버 구성하기: <a href="https://juyoung-hong.github.io/infra/ocioke/">링크</a></li>
</ul>

<p><br /></p>

<h1 id="cicd-전용-vm-생성">CI/CD 전용 VM 생성</h1>

<p><br /></p>

<p>Jenkins를 설치하여 소스코드에 변경사항이 발생했을때 docker 이미지를 빌드하고 OKE에 반영하는 등 일련의 작업을 수행할 CI/CD 전용 VM을 새로 생성합니다.</p>

<ul>
  <li>아래 글과 같이 CI/CD에 사용할 Subnet을 하나 더 구성합니다.
    <ul>
      <li>오라클 클라우드로 무료 인프라 네트워크 구성하기: <a href="https://juyoung-hong.github.io/infra/ocinetwork/">링크</a></li>
    </ul>
  </li>
  <li>이후 아래 글에서 Bastion 서버를 만든 것처럼 Always Free shape으로 Compute Instance를 1개 더 생성합니다.
    <ul>
      <li>오라클 클라우드에 무료 bastion 서버 구성하기: <a href="https://juyoung-hong.github.io/infra/ocibastion/">링크</a></li>
    </ul>
  </li>
  <li>swap memory 설정, OCI CLI, docker, kubectl 설치 등을 아래 글과 같이 수행합니다.
    <ul>
      <li>오라클 쿠버네티스 접속 환경 설정하기: <a href="https://juyoung-hong.github.io/infra/ocibastion/">링크</a></li>
    </ul>
  </li>
</ul>

<p>위 과정을 모두 수행하면 되지만 이미 Bastion 서버를 구성할때 상당부분을 완료하였기에 아래와 같은 순서로 작업을 진행해보겠습니다.</p>

<ol>
  <li>CI/CD 전용 Subnet 생성</li>
  <li>Bastion 서버 종료 및 Custom Image 생성</li>
  <li>Custom Image를 복제하여 CI/CD VM 생성</li>
  <li>CI/CD VM에 Jenkins 설치</li>
</ol>

<p><br /></p>

<h2 id="cicd-전용-subnet-생성">CI/CD 전용 Subnet 생성</h2>

<p><br /></p>

<h3 id="route-table-생성">Route Table 생성</h3>

<p><br /></p>

<p><img src="/assets/images/2026-05-05-setcicd/create_routetable.jpeg" alt="create_routetable" /></p>

<p>먼저 생성해뒀던 VCN의 상세 페이지에가서 Routing 탭으로 이동한 뒤, Create Route Table 버튼을 클릭하여 서브넷을 생성합니다.</p>

<p><img src="/assets/images/2026-05-05-setcicd/create_routetable2.jpeg" alt="create_routetable2" /></p>

<p>CI/CD VM은 private 한 서브넷에 두지만 인터넷에 대한 접속은 필요하므로 Egress Rule에 0.0.0.0/0 으로 NAT Gateway를 사용하는 Rule을 추가하고, OCI의 Container Registry에 접근할 수 있도록 Service Gateway도 추가해줍니다.</p>

<p><img src="/assets/images/2026-05-05-setcicd/create_routetable3.jpeg" alt="create_routetable3" /></p>

<p>최종적으로 위와 같이 route table이 생성됩니다.</p>

<p><br /></p>

<h3 id="security-list-생성">Security List 생성</h3>

<p><br /></p>

<p><img src="/assets/images/2026-05-05-setcicd/create_securitylist.jpeg" alt="create_securitylist" /></p>

<p>이제 VCN 상세페이지의 Security List 탭에 가서 Security List를 생성해줍니다.</p>

<p><img src="/assets/images/2026-05-05-setcicd/create_securitylist2.jpeg" alt="create_securitylist2" /></p>

<p>Bastion에서 접속할 수 있도록 Ingress Rule을 설정해주고, Internet Access가 가능하도록 Egress Rule도 설정해줍니다.</p>

<p><br /></p>

<h3 id="subnet-생성">Subnet 생성</h3>

<p><br /></p>

<p><img src="/assets/images/2026-05-05-setcicd/create_subnet.jpeg" alt="create_subnet" /></p>

<p>마지막으로 VCN의 상세 페이지에가서 Subnet 탭으로 이동한 뒤, Create Subnet 버튼을 클릭하여 서브넷을 생성합니다.</p>

<p><img src="/assets/images/2026-05-05-setcicd/create_subnet2.jpeg" alt="create_subnet2" /></p>

<p>Subnet의 이름과 사용가능한 IP 대역을 선택하고, 아까 생성한 Route table, Security List가 적용되도록 선택하여 Private Subnet을 생성합니다.</p>

<p><br /></p>

<h2 id="cicd-전용-vm-생성-1">CI/CD 전용 VM 생성</h2>

<p><br /></p>

<h3 id="bastion-vm-활용-custom-image-생성">Bastion VM 활용 Custom Image 생성</h3>

<p><br /></p>

<p><img src="/assets/images/2026-05-05-setcicd/stop_vm.jpeg" alt="stop_vm" /></p>

<p>이제 Bastion VM의 상세 페이지로 이동하여 실행중인 VM을 잠시 정지해줍니다.</p>

<p><img src="/assets/images/2026-05-05-setcicd/create_custom_image.jpeg" alt="create_custom_image" /></p>

<p><img src="/assets/images/2026-05-05-setcicd/create_custom_image2.jpeg" alt="create_custom_image2" /></p>

<p>VM이 완전히 정지가 된 이후에는 create_custom_image를 선택하여 이미지를 만들어줍니다.</p>

<p>조금의 시간이 지나면 Custom Image의 생성이 완료되고, 신규 VM을 만들면 됩니다.</p>

<p><br /></p>

<h3 id="cicd-vm-생성">CI/CD VM 생성</h3>

<p><br /></p>

<p><img src="/assets/images/2026-05-05-setcicd/select_custom_image.jpeg" alt="select_custom_image" /></p>

<p>이제 아래의 글과 같이 무료 compute 인스턴스를 1개 추가로 생성해줍니다.</p>

<p>아래의 글을 참고하여 Bastion을 만들때와 유사하게 VCN, Subnet, Shape 등을 선택하고, ssh-key도 잊지 않고 추가하여 생성해주되, Image는 아까 만든 Custom Image를 선택하여 생성해줍니다.</p>

<ul>
  <li>오라클 클라우드에 무료 bastion 서버 구성하기: <a href="https://juyoung-hong.github.io/infra/ocibastion/">링크</a></li>
</ul>

<p><br /></p>

<h3 id="cicd-vm-접속">CI/CD VM 접속</h3>

<p><br /></p>

<p>이제 잘 생성되었는지 접속하기 위하여 중지해두었던 bastion은 다시 start 해주고, vscode의 remote 설정에 아래와 같이 접속을 위한 config를 작성해줍니다.</p>

<p><br /></p>

<h3 id="custom-image-삭제">Custom Image 삭제</h3>

<p><br /></p>

<p><img src="/assets/images/2026-05-05-setcicd/delete_custom_image.jpeg" alt="delete_custom_image" /></p>

<p>혹시 모를 과금을 방지하기 위해 생성한 custom image는 삭제해줍니다.</p>

<p><br /></p>

<h2 id="jenkins-설치">Jenkins 설치</h2>

<p><br /></p>

<p><img src="/assets/images/2026-05-05-setcicd/run_jenkins.jpeg" alt="run_jenkins" /></p>

<p>이제 Jenkins 설치를 위해 CI/CD VM에서 아래의 명령어를 입력하여 open jdk 17 버전을 설치해줍니다.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>apt update
<span class="nb">sudo </span>apt <span class="nb">install </span>openjdk-21-jdk <span class="nt">-y</span>
<span class="nb">mkdir </span>jenkins
<span class="nb">cd </span>jenkins
wget https://updates.jenkins.io/latest/jenkins.war
<span class="nv">JENKINS_HOME</span><span class="o">=</span>jenkins 
<span class="nb">nohup </span>java <span class="nt">-jar</span> jenkins.war <span class="nt">--httpPort</span><span class="o">=</span>8080 &amp;
</code></pre></div></div>

<p>이후 노트북 단말에서 bastion을 통해서 안전하게 ci/cd 머신에 접근할 수 있도록 아래의 명령어를 통해 8080포트의 터널링을 설정합니다.</p>

<p>cicd_vm은 ~/.ssh/config 경로에 미리 지정한 ssh 접속 관련 설정 파일에 명시되어 있어 그대로 사용하였습니다.</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="s">Host cicd_vm</span>
  <span class="s">HostName 10.0.x.x</span>
  <span class="s">User ubuntu</span>
  <span class="s">IdentityFile /Users/jyhong/.ssh/prd_oci</span>
  <span class="s">ProxyJump bastion</span>
</code></pre></div></div>

<p><img src="/assets/images/2026-05-05-setcicd/set_tunnel.jpeg" alt="set_tunnel" /></p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh <span class="nt">-L</span> 8080:localhost:8080 cicd_vm
</code></pre></div></div>

<p>터널링 연결이 완료된 이후에는 브라우저에서 https://localhost:8080 을 입력하여 jenkins에 접속하고, 최초 접속시에는 jenkins 구동시에 admin password를 입력하여 설치를 마무리합니다.</p>

<p><img src="/assets/images/2026-05-05-setcicd/jenkins_admin.jpeg" alt="jenkins_admin" /></p>

<p><img src="/assets/images/2026-05-05-setcicd/jenkins_install.jpeg" alt="jenkins_install" /></p>

<p>Install Suggested Packages 클릭 후 조금 기다리면 아래 이미지와 같이 설치를 진행합니다.</p>

<p><img src="/assets/images/2026-05-05-setcicd/jenkins_install2.jpeg" alt="jenkins_install2" /></p>

<p>설치가 끝난 이후에는 아래와 같이 ADMIN 계정 세팅을 진행합니다.</p>

<p><img src="/assets/images/2026-05-05-setcicd/jenkins_install3.jpeg" alt="jenkins_install3" /></p>

<p><img src="/assets/images/2026-05-05-setcicd/jenkins_install4.jpeg" alt="jenkins_install4" /></p>

<p>마지막으로 아래와 같이 Jenkins 구성이 끝나고 메인 화면을 볼 수 있습니다.</p>

<p><img src="/assets/images/2026-05-05-setcicd/jenkins_main.jpeg" alt="jenkins_main" /></p>

<p>다음으로는 지난번 원격 리파지토리에 올려두었던 소스를 OKE에 배포해보고, 배포 파이프라인은 Jenkins에 구성해서, commit 하는 순간 OKE에 배포될 수 있도록 추가 설정을 진행하겠습니다.</p>]]></content><author><name>Juyoung Hong</name><email>hjy_stat@naver.com</email></author><category term="infra" /><category term="oracle-cloud" /><category term="jenkins" /><category term="CI" /><category term="CD" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">오라클 쿠버네티스 접속 환경 설정하기</title><link href="https://juyoung-hong.github.io/infra/okesetting/" rel="alternate" type="text/html" title="오라클 쿠버네티스 접속 환경 설정하기" /><published>2026-05-01T00:00:00+09:00</published><updated>2026-05-01T00:00:00+09:00</updated><id>https://juyoung-hong.github.io/infra/okesetting</id><content type="html" xml:base="https://juyoung-hong.github.io/infra/okesetting/"><![CDATA[<p><br /></p>

<h1 id="오라클-쿠버네티스-접속-환경-설정하기">오라클 쿠버네티스 접속 환경 설정하기</h1>

<p><br /></p>

<p>오늘은 지난 글에 이어서 오라클 클라우드에 접속할 수 있는 환경을 Bastion에 설정해 보겠습니다.</p>

<p>오라클 쿠버네티스 클러스터와 Bastion이 만들어져 있는 상태여야 하므로 이전 글과 함께 봐주시면 감사하겠습니다.</p>

<ul>
  <li>오라클 클라우드로 무료 인프라 네트워크 구성하기: <a href="https://juyoung-hong.github.io/infra/ocinetwork/">링크</a></li>
  <li>오라클 클라우드에 무료 bastion 서버 구성하기: <a href="https://juyoung-hong.github.io/infra/ocibastion/">링크</a></li>
</ul>

<p><br /></p>

<h1 id="oci-cli-설정">OCI CLI 설정</h1>

<p><br /></p>

<p>현재 Bastion과 OKE가 만들어져 있는 상태에서 생성된 OKE에 접근할 수 있도록 Bastion에 OCI CLI를 설치하고 설정을 진행하겠습니다.</p>

<p><br /></p>

<h2 id="bation-swap-메모리-설정">Bation swap 메모리 설정</h2>

<p><br /></p>

<p>Always Free 사이즈인 VM.Standard.E2.1.Micro 로 만들어진 Bastion은 메모리가 1GB 밖에 안되기 때문에 조금만 무거운 작업을 하면 자주 먹통이 되곤합니다.</p>

<p><img src="/assets/images/2026-05-01-okesetting/set_swap_memory.jpeg" alt="set_swap_memory" /></p>

<p>작업을 수행하는 과정에 이러한 현상이 발생하지 않도록 아래 명령어를 통해 스토리지의 일부를 메모리로 활용할 수 있도록 해줍니다.</p>

<p><br /></p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo dd </span><span class="k">if</span><span class="o">=</span>/dev/zero <span class="nv">of</span><span class="o">=</span>/swapfile <span class="nv">bs</span><span class="o">=</span>1M <span class="nv">count</span><span class="o">=</span>4096
<span class="nb">sudo chown </span>root:root /swapfile
<span class="nb">sudo chmod </span>600 /swapfile
<span class="nb">sudo </span>mkswap /swapfile
<span class="nb">sudo </span>swapon /swapfile
</code></pre></div></div>

<p><br /></p>

<p>Bastion에서 파일을 손쉽게 수정할 수 있도록 아래 명령어로 Vim을 설치합니다.</p>

<p><br /></p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>apt-get update
<span class="nb">sudo </span>apt-get <span class="nb">install </span>vim
</code></pre></div></div>

<p><br /></p>

<p>Vim 설치 이후, VM이 재기동된 이후에도 이러한 스왑메모리 설정이 유지될 수 있도록 /etc/fstab 파일을 열어서 아래와 같이 수정합니다.</p>

<p><img src="/assets/images/2026-05-01-okesetting/edit_fstab.jpeg" alt="edit_fstab" /></p>

<p><br /></p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>vi /etc/fstab
/swapfile swap swap defaults 0 0
</code></pre></div></div>

<p><br /></p>

<p>마지막으로 아래 명령어를 통해, 잘 설정되었는지 확인합니다.</p>

<p><img src="/assets/images/2026-05-01-okesetting/check_swap_memory.jpeg" alt="check_swap_memory" /></p>

<p><br /></p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>swapon <span class="nt">-s</span>
</code></pre></div></div>

<p><br /></p>

<h2 id="oci-cli-설치">OCI CLI 설치</h2>

<p><br /></p>

<p>이제 본격적으로 OCI CLI를 설치하기 위해 아래 명령어를 이용하여 OCI CLI를 다운로드 받습니다.</p>

<p>Default 옵션을 사용하기 위해 이후 몇가지 문의에 대해서는 엔터를 입력하여 넘어갔습니다.</p>

<p>버전을 확인하면 잘 설치된것을 확인할 수 있습니다.</p>

<p><img src="/assets/images/2026-05-01-okesetting/install_oci_cli.jpeg" alt="install_oci_cli" /></p>

<p><br /></p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>bash <span class="nt">-c</span> <span class="s2">"</span><span class="si">$(</span>curl <span class="nt">-L</span> https://raw.githubusercontent.com/oracle/oci-cli/master/scripts/install/install.sh<span class="si">)</span><span class="s2">"</span>
<span class="nb">source</span> ./.bashrc
oci <span class="nt">--version</span>
</code></pre></div></div>

<p><br /></p>

<h2 id="oci-cli-설정-1">OCI CLI 설정</h2>

<p><br /></p>

<p>이제 클라우드 자원 제어를 위한 API Key pair를 생성합니다.</p>

<p>테넌시의 OCID와 사용자의 OCID가 필요한데, 아래와 같이 확인할 수 있습니다.</p>

<p><br /></p>

<h3 id="테넌시-ocid-확인">테넌시 OCID 확인</h3>

<p><br /></p>

<p><img src="/assets/images/2026-05-01-okesetting/tenancy_ocid.jpeg" alt="tenancy_ocid" /></p>

<p><br /></p>

<h3 id="user-ocid-확인">User OCID 확인</h3>

<p><br /></p>

<p><img src="/assets/images/2026-05-01-okesetting/user_ocid.jpeg" alt="user_ocid" /></p>

<p><br /></p>

<p><img src="/assets/images/2026-05-01-okesetting/setup_config.jpeg" alt="setup_config" /></p>

<p>이제 아래 명령어를 가지고 설정을 진행합니다.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>oci setup config
</code></pre></div></div>

<p>이제 생성된 API public Key를 OCI 사용자 API Key에 등록합니다.</p>

<p><img src="/assets/images/2026-05-01-okesetting/cat_ssh_publickey.jpeg" alt="cat_ssh_publickey" /></p>

<p>먼저 생성된 oci api key 중 public key를 복사합니다.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cat</span> ~/.oci/oci_api_key_public.pem
</code></pre></div></div>

<p>이후 User OCID를 확인했던 아래 메뉴로 이동하여 복사한 API Key를 붙여넣기합니다.</p>

<p><img src="/assets/images/2026-05-01-okesetting/ociconsole_apikey.jpeg" alt="ociconsole_apikey" /></p>

<p><img src="/assets/images/2026-05-01-okesetting/add_apikey.jpeg" alt="add_apikey" /></p>

<p><img src="/assets/images/2026-05-01-okesetting/check_ocicli.jpeg" alt="check_ocicli" /></p>

<p>API Key 등록이 끝난 후에는 아래 명령어로 OCI CLI가 정상 동작하는지 확인합니다.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>oci os ns get
oci iam region list <span class="nt">--output</span> table
</code></pre></div></div>

<p><br /></p>

<h1 id="kubectl-설정">Kubectl 설정</h1>

<p><br /></p>

<p>이제 아래 명령어를 가지고 kubectl을 설치합니다.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>apt-get update
<span class="nb">sudo </span>apt-get <span class="nb">install</span> <span class="nt">-y</span> apt-transport-https ca-certificates curl gnupg
curl <span class="nt">-fsSL</span> https://pkgs.k8s.io/core:/stable:/v1.36/deb/Release.key | <span class="nb">sudo </span>gpg <span class="nt">--dearmor</span> <span class="nt">-o</span> /etc/apt/keyrings/kubernetes-apt-keyring.gpg
<span class="nb">sudo chmod </span>644 /etc/apt/keyrings/kubernetes-apt-keyring.gpg
<span class="nb">echo</span> <span class="s1">'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.36/deb/ /'</span> | <span class="nb">sudo tee</span> /etc/apt/sources.list.d/kubernetes.list
<span class="nb">sudo chmod </span>644 /etc/apt/sources.list.d/kubernetes.list
<span class="nb">sudo </span>apt-get update
<span class="nb">sudo </span>apt-get <span class="nb">install</span> <span class="nt">-y</span> kubectl
</code></pre></div></div>

<p>설치 이후 잘 설치되었는지 아래의 명령어로 확인해봅니다.</p>

<p><img src="/assets/images/2026-05-01-okesetting/install_kubectl.jpeg" alt="install_kubectl" /></p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>kubectl version <span class="nt">--output</span><span class="o">=</span>yaml
</code></pre></div></div>

<p><br /></p>

<h2 id="kubeconfig-설정">Kubeconfig 설정</h2>

<p><br /></p>

<p>이제 bastion에 설치한 kubectl을 통해서 OKE Cluster에 접근할 수 있도록 kubeconfig 파일을 구성합니다.</p>

<p>아래와 같이 OKE Cluster 상세 화면에서 Access Cluster 메뉴를 클릭합니다.</p>

<p><img src="/assets/images/2026-05-01-okesetting/access_cluster.jpeg" alt="access_cluster" /></p>

<p><img src="/assets/images/2026-05-01-okesetting/access_cluster2.jpeg" alt="access_cluster2" /></p>

<p>Local Access를 클릭한 이후 노출되는 아래의 명령어들을 입력하여 구성합니다.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>oci <span class="nt">-v</span>
<span class="nb">mkdir</span> <span class="nt">-p</span> <span class="nv">$HOME</span>/.kube
oci ce cluster create-kubeconfig <span class="nt">--cluster-id</span> ocid1.cluster.oc1.ap-chuncheon-1.aaa....
<span class="nb">export </span><span class="nv">KUBECONFIG</span><span class="o">=</span><span class="nv">$HOME</span>/.kube/config
</code></pre></div></div>

<p><img src="/assets/images/2026-05-01-okesetting/access_cluster3.jpeg" alt="access_cluster3" /></p>

<p>잘 설정이 되면 아래의 명령어로 현재 구성된 클러스터의 노드 정보를 가져올 수 있습니다.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>kubectl get nodes
</code></pre></div></div>

<p><br /></p>

<h2 id="docker-설치">Docker 설치</h2>

<p>이제 아래 명령어를 가지고 docker를 설치해줍니다.</p>

<p><br /></p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Add Docker's official GPG key:</span>
<span class="nb">sudo </span>apt update
<span class="nb">sudo </span>apt <span class="nb">install </span>ca-certificates curl
<span class="nb">sudo install</span> <span class="nt">-m</span> 0755 <span class="nt">-d</span> /etc/apt/keyrings
<span class="nb">sudo </span>curl <span class="nt">-fsSL</span> https://download.docker.com/linux/ubuntu/gpg <span class="nt">-o</span> /etc/apt/keyrings/docker.asc
<span class="nb">sudo chmod </span>a+r /etc/apt/keyrings/docker.asc

<span class="c"># Add the repository to Apt sources:</span>
<span class="nb">sudo tee</span> /etc/apt/sources.list.d/docker.sources <span class="o">&lt;&lt;</span><span class="no">EOF</span><span class="sh">
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: </span><span class="si">$(</span><span class="nb">.</span> /etc/os-release <span class="o">&amp;&amp;</span> <span class="nb">echo</span> <span class="s2">"</span><span class="k">${</span><span class="nv">UBUNTU_CODENAME</span><span class="k">:-</span><span class="nv">$VERSION_CODENAME</span><span class="k">}</span><span class="s2">"</span><span class="si">)</span><span class="sh">
Components: stable
Architectures: </span><span class="si">$(</span>dpkg <span class="nt">--print-architecture</span><span class="si">)</span><span class="sh">
Signed-By: /etc/apt/keyrings/docker.asc
</span><span class="no">EOF

</span><span class="nb">sudo </span>apt update
<span class="nb">sudo </span>apt <span class="nb">install </span>docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
</code></pre></div></div>

<p><img src="/assets/images/2026-05-01-okesetting/install_docker.jpeg" alt="install_docker" /></p>

<p>설치가 끝난 이후에는 아래 명령어로 설치가 잘 되었고 정상 실행중인지 확인합니다.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>systemctl status docker
</code></pre></div></div>

<p><img src="/assets/images/2026-05-01-okesetting/config_docker.jpeg" alt="config_docker" /></p>

<p>이후 ubuntu user가 super user 권한 없이도 docker 명령어를 수행 할 수 있도록 아래 명령어로 권한을 부여해주고, nginx 이미지를 다운로드 받습니다.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>usermod <span class="nt">-aG</span> docker ubuntu
newgrp docker
docker pull nginx
</code></pre></div></div>

<p><br /></p>

<h2 id="쿠버네티스-클러스터에-배포하기">쿠버네티스 클러스터에 배포하기</h2>

<p><br /></p>

<h3 id="worker-node-route-rule-수정">Worker Node Route Rule 수정</h3>

<p><br /></p>

<p><img src="/assets/images/2026-05-01-okesetting/set_NAT_rules.jpeg" alt="set_NAT_rules" /></p>

<p>worker node가 외부 인터넷에서 nginx 이미지를 다운로드해서 배포할 수 있도록 Worker Node Subnet에 NAT Gateway를 사용하는 Route Rule을 추가합니다.</p>

<p><br /></p>

<h3 id="worker-node-egress-rule-수정">Worker Node Egress Rule 수정</h3>

<p><br /></p>

<p><img src="/assets/images/2026-05-01-okesetting/set_Egress_rule.jpeg" alt="set_Egress_rule" /></p>

<p>worker node가 외부 인터넷에서 nginx 이미지를 다운로드해서 배포할 수 있도록 Worker Node Subnet에 Egress Rule도 추가합니다.</p>

<p><br /></p>

<h3 id="oke-배포하기">OKE 배포하기</h3>

<p><br /></p>

<p>이제 준비된 nginx 이미지를 OKE 클러스터에 배포해보겠습니다.</p>

<p>저는 아래와 같은 yaml파일을 작성해서 deployments 폴더 안에 nginx.yaml파일로 저장하였습니다.</p>

<p>무료로 loadbalancer를 사용할 수 있도록 shape은 flex로 하고 min, max 값은 무료 제한인 10으로 설정하였습니다.</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">apiVersion</span><span class="pi">:</span> <span class="s">apps/v1</span>
<span class="na">kind</span><span class="pi">:</span> <span class="s">Deployment</span>
<span class="na">metadata</span><span class="pi">:</span>
  <span class="na">name</span><span class="pi">:</span> <span class="s">nginx-deployment</span>
  <span class="na">labels</span><span class="pi">:</span>
    <span class="na">app</span><span class="pi">:</span> <span class="s">nginx</span>
<span class="na">spec</span><span class="pi">:</span>
  <span class="na">replicas</span><span class="pi">:</span> <span class="m">3</span>
  <span class="na">selector</span><span class="pi">:</span>
    <span class="na">matchLabels</span><span class="pi">:</span>
      <span class="na">app</span><span class="pi">:</span> <span class="s">nginx</span>
  <span class="na">template</span><span class="pi">:</span>
    <span class="na">metadata</span><span class="pi">:</span>
      <span class="na">labels</span><span class="pi">:</span>
        <span class="na">app</span><span class="pi">:</span> <span class="s">nginx</span>
    <span class="na">spec</span><span class="pi">:</span>
      <span class="na">containers</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">nginx</span>
        <span class="na">image</span><span class="pi">:</span> <span class="s">docker.io/library/nginx:latest</span>
        <span class="na">ports</span><span class="pi">:</span>
        <span class="pi">-</span> <span class="na">containerPort</span><span class="pi">:</span> <span class="m">80</span>
        <span class="na">resources</span><span class="pi">:</span>
          <span class="na">requests</span><span class="pi">:</span>
            <span class="na">cpu</span><span class="pi">:</span> <span class="s2">"</span><span class="s">500m"</span>
            <span class="na">memory</span><span class="pi">:</span> <span class="s2">"</span><span class="s">512Mi"</span>
<span class="nn">---</span>
<span class="na">apiVersion</span><span class="pi">:</span> <span class="s">v1</span>
<span class="na">kind</span><span class="pi">:</span> <span class="s">Service</span>
<span class="na">metadata</span><span class="pi">:</span>
  <span class="na">name</span><span class="pi">:</span> <span class="s">nginx-service</span>
  <span class="na">annotations</span><span class="pi">:</span>
    <span class="na">service.beta.kubernetes.io/oci-load-balancer-shape</span><span class="pi">:</span> <span class="s2">"</span><span class="s">flexible"</span>
    <span class="na">service.beta.kubernetes.io/oci-load-balancer-shape-flex-min</span><span class="pi">:</span> <span class="s2">"</span><span class="s">10"</span>
    <span class="na">service.beta.kubernetes.io/oci-load-balancer-shape-flex-max</span><span class="pi">:</span> <span class="s2">"</span><span class="s">10"</span>
  <span class="na">labels</span><span class="pi">:</span>
    <span class="na">app</span><span class="pi">:</span> <span class="s">nginx</span>
<span class="na">spec</span><span class="pi">:</span>
  <span class="na">type</span><span class="pi">:</span> <span class="s">LoadBalancer</span>
  <span class="na">ports</span><span class="pi">:</span>
  <span class="pi">-</span> <span class="na">port</span><span class="pi">:</span> <span class="m">80</span>
    <span class="na">targetPort</span><span class="pi">:</span> <span class="m">80</span>
    <span class="na">protocol</span><span class="pi">:</span> <span class="s">TCP</span>
  <span class="na">selector</span><span class="pi">:</span>
    <span class="na">app</span><span class="pi">:</span> <span class="s">nginx</span>
</code></pre></div></div>

<p><img src="/assets/images/2026-05-01-okesetting/deploy_kubernetes.jpeg" alt="deploy_kubernetes" /></p>

<p>이후 아래 명령어로 배포하고, 쿠버네티스 클러스터의 상태를 확인합니다.</p>

<p>모든 pod가 정상적으로 running 상태이고, service도 정상적으로 생성되었습니다.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>kubectl apply <span class="nt">-f</span> deployments/nginx.yaml
kubectl get all
</code></pre></div></div>

<p><img src="/assets/images/2026-05-01-okesetting/create_lb.jpeg" alt="create_lb" /></p>

<p>이제 OCI 콘솔의 Loadbalancer를 확인하면 LB가 하나 생성되어 있는 것을 확인할 수 있습니다.</p>

<p>LB의 public IP는 service의 external IP와도 일치하고, 이 IP 주소를 브라우저에 입력하고 접속해보면, 아래와 같이 nginx가 잘 배포 되어 있는 것을 확인할 수 있습니다.</p>

<p><img src="/assets/images/2026-05-01-okesetting/access_nginx.jpeg" alt="access_nginx" /></p>

<p>다음으로는 jenkins로 CI/CD 구성을 하고 직접 만든 앱을 배포해보겠습니다.</p>]]></content><author><name>Juyoung Hong</name><email>hjy_stat@naver.com</email></author><category term="infra" /><category term="oracle-cloud" /><category term="oke" /><category term="kubernetes" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">간단한 React 앱 구성 후 OKE에 배포하기</title><link href="https://juyoung-hong.github.io/devops/github_organization/" rel="alternate" type="text/html" title="간단한 React 앱 구성 후 OKE에 배포하기" /><published>2026-04-20T00:00:00+09:00</published><updated>2026-04-20T00:00:00+09:00</updated><id>https://juyoung-hong.github.io/devops/github_organization</id><content type="html" xml:base="https://juyoung-hong.github.io/devops/github_organization/"><![CDATA[<p><br /></p>

<h1 id="github-organization-구성하기">Github Organization 구성하기</h1>

<p><br /></p>

<p>오늘은 지난 글에서 만들었던 OKE에 배포할 간단한 어플리케이션을 만들어 보겠습니다.</p>

<p>Github는 무료로 git에 대한 원격 저장소를 제공하며, 특히 Organization 기능을 활용하면 여러개의 Repo들을 하나로 묶어서 관리하는 등 좀 더 효율적으로 협업할 수 있습니다.</p>

<p>이번에는 무료로 사용할 수 있는 github organization을 생성하여 소스코드 형상 관리 시스템을 세팅해보겠습니다.</p>

<p><br /></p>

<h2 id="새로운-organization-생성하기">새로운 Organization 생성하기</h2>

<p><br /></p>

<p><img src="/assets/images/2026-04-20-github_organization/new_organization.jpeg" alt="new_organization" /></p>

<p>github 계정으로 로그인 한 뒤 화면 우측 상단의 “+” 버튼을 클릭하고, “New organization”을 클릭합니다.</p>

<p><img src="/assets/images/2026-04-20-github_organization/new_organization2.jpeg" alt="new_organization2" /></p>

<p>무료로 사용할 수 있도록 왼쪽의 “Create a free organization”을 클릭합니다.</p>

<p><img src="/assets/images/2026-04-20-github_organization/new_organization3.jpeg" alt="new_organization3" /></p>

<p>Organization Name을 기존의 다른 조직과 겹치지 않도록 입력하고, contact email 주소를 입력한 뒤, “My personnel account”로 선택 후 아래의 “로봇이 아닙니다”를 풀고 약관에 동의하면 Organization을 생성할 수 있습니다.</p>

<p><img src="/assets/images/2026-04-20-github_organization/new_organization4.jpeg" alt="new_organization4" /></p>

<p>초대할 동료가 있다면 초대하고, Complete setup 버튼을 클릭하면 Organization이 생성됩니다.</p>

<p><br /></p>

<h2 id="새로운-repo-생성하기">새로운 Repo 생성하기</h2>

<p><br /></p>

<p><img src="/assets/images/2026-04-20-github_organization/new_repo.jpeg" alt="new_repo" /></p>

<p>Organization이 생성되면 Repositories 탭을 클릭한 후 화면에서 오른쪽 상단의 “New repository” 버튼을 클릭하여 Repo를 생성합니다.</p>

<p><img src="/assets/images/2026-04-20-github_organization/new_repo2.jpeg" alt="new_repo2" /></p>

<p>이후로는 일반적으로 github에서 repo를 만드는 것과 동일하게 repository에 사용할 이름 등을 입력하고 Create Repository를 클릭하여 생성합니다.</p>

<p><img src="/assets/images/2026-04-20-github_organization/clone_repo.jpeg" alt="clone_repo" /></p>

<div class="language-zsh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git clone <span class="o">{</span>repository url<span class="o">}</span>
</code></pre></div></div>

<p>repository 생성 완료후에는 생성된 repository에서 작업할 수 있도록 터미널을 열어, 위 명령어로 local에 repo를 클론해오고 IDE로 작업할 폴더를 열어서 준비합니다.</p>

<p><img src="/assets/images/2026-04-20-github_organization/open_repo.jpeg" alt="open_repo" /></p>

<p>저는 IDE로 google의 anti-gravity를 사용하겠습니다.</p>

<p><br /></p>

<h2 id="react-project-세팅">React project 세팅</h2>

<p><br /></p>

<p>프론트엔드쪽 관련해서는 잘 모르지만 react 관련 앱들이 대부분 주류로 사용되는 것 같습니다.</p>

<p>올해 코딩애플님의 react 강의를 들었었고, 강의 내용과 같이 기본적인 프로젝트 세팅을 진행해 보겠습니다.</p>

<p>제 PC에는 node.js 및 npm이 설치되어 있으므로 아래 명령어로 Vite 프로젝트를 시작해 보겠습니다.</p>

<p><img src="/assets/images/2026-04-20-github_organization/create_vite_project.jpeg" alt="create_vite_project" /></p>

<div class="language-zsh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>npm create vite@latest <span class="nb">.</span>
</code></pre></div></div>

<p>IDE로 작업 폴더를 열고, Node.js가 설치되어있다면 위 명령어로 현재 폴더에 react + typescript 개발 환경을 구성합니다.</p>

<p><img src="/assets/images/2026-04-20-github_organization/git_commit.jpeg" alt="git_commit" /></p>

<div class="language-zsh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git add <span class="k">*</span>
git commit <span class="nt">-m</span> <span class="s2">"Initial Commit"</span>
git push origin
</code></pre></div></div>

<p>위 명령어로 지금까지 구성된 내용을 커밋하고 remote repository에 반영합니다.</p>]]></content><author><name>Juyoung Hong</name><email>hjy_stat@naver.com</email></author><category term="devops" /><category term="github" /><category term="organization" /><category term="react" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">오라클 클라우드에 무료 관리형 쿠버네티스 서버 구성하기</title><link href="https://juyoung-hong.github.io/infra/ocioke/" rel="alternate" type="text/html" title="오라클 클라우드에 무료 관리형 쿠버네티스 서버 구성하기" /><published>2026-04-11T00:00:00+09:00</published><updated>2026-04-11T00:00:00+09:00</updated><id>https://juyoung-hong.github.io/infra/ocioke</id><content type="html" xml:base="https://juyoung-hong.github.io/infra/ocioke/"><![CDATA[<p><br /></p>

<h1 id="오라클-클라우드에-무료-관리형-쿠버네티스-서버-구성하기">오라클 클라우드에 무료 관리형 쿠버네티스 서버 구성하기</h1>

<p><br /></p>

<p>오늘은 지난 글에 이어서 오라클 클라우드에서 제공하는 관리형 쿠버네티스 서비스인 OKE(Oracle Kubernetes Engine)를 구성해보겠습니다.</p>

<p>VCN이 만들어져 있는 상태여야 하므로 아래의 이전글과 함께 봐주시면 감사하겠습니다.</p>

<ul>
  <li>오라클 클라우드로 무료 인프라 네트워크 구성하기: <a href="https://juyoung-hong.github.io/infra/ocinetwork/">링크</a></li>
</ul>

<p><br /></p>

<h1 id="private-oke를-위한-네트워크-추가-구성하기">Private OKE를 위한 네트워크 추가 구성하기</h1>

<p><br /></p>

<h2 id="cni-container-network-interface">CNI (Container Network Interface)</h2>

<p><br /></p>

<p>CNI (Container Network Interface)는 쿠버네티스 내부에서 파드간 통신을 위해 필요한 중요한 요소입니다.</p>

<p>Flannel이라는 플러그인을 주로 사용하는데, 노드에 할당된 IP 주소 범위를 관리하고, 각 노드에 가상 네트워크 인터페이스를 생성해서 파드 간의 통신을 중계하는 역할을 합니다.</p>

<p>OCI의 경우 Flannel을 사용하는 Overlay Network를 구성하는 방법 외에도 VCN Native Pod Networking CNI 옵션을 제공합니다.</p>

<p>application이 VCN의 IP 주소를 사용할 필요가 없고, 워커노드 별로 매우 밀도높은 Pod를 배치하는 경우, Flannel Overlay CNI를 선택할 것을 권고하며, Pod가 VCN의 IP 주소를 필요로하며 안정적인 네트워크 성능을 요구하는 경우 VCN Native 방법을 선택하라고 합니다.</p>

<p><br /></p>

<h2 id="vcn-native-네트워크-구성">VCN Native 네트워크 구성</h2>

<p><br /></p>

<p>Oracle Cloud에 Native한 환경으로 Private Kubernetes 클러스터를 구축하고자 다음 <a href="https://docs.oracle.com/en-us/iaas/Content/ContEng/Concepts/contengnetworkconfigexample.htm#example-oci-cni-privatek8sapi_privateworkers_publiclb">링크</a>의 Example 4를 참고하였습니다.</p>

<p><img src="/assets/images/2026-04-11-ocioke/conteng-network-oci-cni-eg4.jpeg" alt="conteng-network-oci-cni-eg4" /></p>

<p>우리는 DMZ 구간인 Public 구간에 Bastion을 구성하였으니, OKE 관련하여 “Kubernetes API Endpoint Subnet”, “Worker Nodes Subnet”, “Pod Subnet”, “LoadBalancers Subnet”이 추가로 구성 필요합니다.</p>

<p>이때 “LoadBalancers Subnet”은 외부에서 접속 할 수 있도록 Public Subnet으로 구성하고, 이외의 나머지 서브넷들은 Private Subnet으로 구성합니다.</p>

<p><br /></p>

<h3 id="route-table-구성">Route Table 구성</h3>

<p><br /></p>

<p>이제 앞으로 구성할 쿠버네티스 관련 리소스들에서 사용할 Route Table을 먼저 구성합니다.</p>

<p><img src="/assets/images/2026-04-11-ocioke/oke_apiendpoint_create_routetable.jpeg" alt="oke_apiendpoint_create_routetable" /></p>

<p>지난 글에서 미리 만들어둔 PRD_MLPLATFORM_VCN에 들어가서 Routing 메뉴를 클릭한 후, Create Route Table을 클릭합니다.</p>

<p><img src="/assets/images/2026-04-11-ocioke/oke_apiendpoint_create_routetable2.jpeg" alt="oke_apiendpoint_create_routetable2" /></p>

<ul>
  <li>Route Table의 이름을 입력하고 Route Rule의 규칙을 입력한 뒤, Create 버튼을 클릭하여 생성합니다. ( 저는 명명규칙에 대해 {Application명}_RouteTable을 사용하였습니다. )</li>
  <li>각 RouteTable에서 사용할 규칙을 정의하여야 하지만 나중에 수정할 수 있으므로 일단 생성만 하고 넘어가겠습니다.</li>
  <li>위 이미지에서는 Kubernetes API Endpoint를 위한 RouteTable 만을 생성하였지만, 마찬가지 방식으로 WorkerNode, Pod, Loadbalancer에서 사용할 RouteTable도 생성해줍니다.</li>
</ul>

<p><img src="/assets/images/2026-04-11-ocioke/oke_routetables.jpeg" alt="oke_routetables" /></p>

<p>결과적으로 위 이미지와 같이 라우트 테이블을 구성해줍니다.</p>

<p><br /></p>

<h3 id="security-list-구성">Security List 구성</h3>

<p><br /></p>

<p>Route Table과 유사하게 Security List도 구성해줍니다.</p>

<p><img src="/assets/images/2026-04-11-ocioke/oke_securitylitsts.jpeg" alt="oke_securitylitsts" /></p>

<p>PRD_MLPLATFORM_VCN에서 Security 메뉴를 클릭한 후, Create Security List을 클릭합니다.</p>

<p><img src="/assets/images/2026-04-11-ocioke/oke_securitylitsts2.jpeg" alt="oke_securitylitsts2" /></p>

<ul>
  <li>Security List의 이름을 입력하고 Security Rule의 규칙을 입력한 뒤, Create 버튼을 클릭하여 생성합니다. ( 저는 명명규칙에 대해 {Application명}_SecurityList를 사용하였습니다. )</li>
  <li>각 Security List에서 사용할 규칙을 정의하여야 하지만 나중에 수정할 수 있으므로 일단 생성만 하고 넘어가겠습니다.</li>
  <li>위 이미지에서는 Kubernetes API Endpoint를 위한 Security List 만을 생성하였지만, 마찬가지 방식으로 WorkerNode, Pod, Loadbalancer에서 사용할 Security List도 생성해줍니다.</li>
</ul>

<p><img src="/assets/images/2026-04-11-ocioke/oke_securitylitsts3.jpeg" alt="oke_securitylitsts3" /></p>

<p>결과적으로 위 이미지와 같이 시큐리티리스트들을 구성해줍니다.</p>

<p><br /></p>

<h3 id="kubernetes-subnet-구성">Kubernetes Subnet 구성</h3>

<p><br /></p>

<p>이제 본격적으로 Subnet들을 구성하겠습니다.</p>

<p>OCI의 Example에서는 Private Subnet for Kubernetes API Endpoint의 CIDR Block을 10.0.0.0/29로 잡았지만, 우리는 이미 Bastion을 위한 DMZ Subnet을 10.0.0.0/24 로 사용중이므로, CIDR Block이 일부 겹칠 수 있습니다.</p>

<p>따라서 예시에 나온 10.0.0.0/29 대신, 10.0.3.0/29를 사용하겠습니다.</p>

<p>VCN을 만들때 함께 생성되었던 private subnet은 이름을 변경하여 Worker Node 들이 사용할 수 있는 Private Subnet으로 사용하겠습니다.</p>

<p>Load Balancer가 사용할 Subnet은 아직 없으므로 새로 생성하고, Bastion은 DMZ Subnet이 이미 있으므로 추가로 만들지 않겠습니다.</p>

<p>정리하면 아래 표와 같습니다.</p>

<table>
  <thead>
    <tr>
      <th style="text-align: center">필요한 Subnet</th>
      <th style="text-align: center">CIDR Block</th>
      <th style="text-align: center">현재 Subnet</th>
      <th style="text-align: center">CIDR Block</th>
      <th style="text-align: center">필요한 작업</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: center">Private Subnet for Kubernetes API Endpoint</td>
      <td style="text-align: center">10.0.0.0/29</td>
      <td style="text-align: center">-</td>
      <td style="text-align: center">-</td>
      <td style="text-align: center">10.0.3.0/29 대역으로 바꿔서 생성</td>
    </tr>
    <tr>
      <td style="text-align: center">Private Subnet for Worker Nodes</td>
      <td style="text-align: center">10.0.1.0/24</td>
      <td style="text-align: center">private subnet-PRD_MLPLATFORM_VCN</td>
      <td style="text-align: center">10.0.1.0/24</td>
      <td style="text-align: center">subnet 이름 변경</td>
    </tr>
    <tr>
      <td style="text-align: center">Private Subnet for Pods</td>
      <td style="text-align: center">10.0.32.0/19</td>
      <td style="text-align: center">-</td>
      <td style="text-align: center">-</td>
      <td style="text-align: center">신규생성</td>
    </tr>
    <tr>
      <td style="text-align: center">Public Subnet for Service Load Balancers</td>
      <td style="text-align: center">10.0.2.0/24</td>
      <td style="text-align: center">-</td>
      <td style="text-align: center">-</td>
      <td style="text-align: center">신규생성</td>
    </tr>
    <tr>
      <td style="text-align: center">Subnet for Bastion</td>
      <td style="text-align: center">10.0.3.0/24</td>
      <td style="text-align: center">DMZ_Subnet</td>
      <td style="text-align: center">10.0.0.0/24</td>
      <td style="text-align: center">-</td>
    </tr>
  </tbody>
</table>

<p>이제 본격적으로 Subnet 생성 작업을 시작하겠습니다.</p>

<p><img src="/assets/images/2026-04-11-ocioke/oke_create_subnet1.jpeg" alt="oke_create_subnet1" /></p>

<p>PRD_MLPLATFORM_VCN에서 Subnets 탭을 선택 한 뒤, Create Subnet 버튼을 클릭하여 서브넷을 생성합니다.</p>

<p><img src="/assets/images/2026-04-11-ocioke/oke_create_subnet2.jpeg" alt="oke_create_subnet2" /></p>

<p><img src="/assets/images/2026-04-11-ocioke/oke_create_subnet3.jpeg" alt="oke_create_subnet3" /></p>

<p><img src="/assets/images/2026-04-11-ocioke/oke_create_subnet4.jpeg" alt="oke_create_subnet4" /></p>

<ul>
  <li>Subnet의 이름을 명명하고, Subnet에 부여할 CIDR Block의 값을 정합니다.</li>
  <li>Subnet에 적용할 route table을 선택하고, Public/Private 여부도 잘 확인해서 선택합니다.</li>
  <li>마지막으로 Security list도 잘 선택하고 Create Subnet 버튼을 클릭합니다.</li>
  <li>비슷한 방식으로 Private Subnet for Pods, Public Subnet for Service Load Balancers 도 생성합니다. Loadbalancer 용 Subnet은 Private이 아닌 Public임에 유의합니다.</li>
</ul>

<p>이제 기존에 존재하던 Subnet의 이름을 변경합니다.</p>

<p><img src="/assets/images/2026-04-11-ocioke/oke_rename_subnet.jpeg" alt="oke_rename_subnet" /></p>

<p>변경할 대상 서브넷의 오른쪽 점세개를 클릭하고 “Edit” 버튼을 클릭합니다.</p>

<p><img src="/assets/images/2026-04-11-ocioke/oke_rename_subnet2.jpeg" alt="oke_rename_subnet2" /></p>

<p>서브넷의 이름과 아까 만든 라우트 테이블을 선택하고 “Save changes” 버튼을 클릭하여 저장합니다.</p>

<p><img src="/assets/images/2026-04-11-ocioke/oke_add_seclist.jpeg" alt="oke_add_seclist" /></p>

<p><img src="/assets/images/2026-04-11-ocioke/oke_add_seclist2.jpeg" alt="oke_add_seclist2" /></p>

<p>Security List를 변경하기 위해 변경사항이 저장된 Subnet을 클릭하여 상세 페이지로 접속한 뒤, Security 탭을 클릭하여 “Add Security List” 버튼을 클릭하여 아까 만들어둔 Security List를 추가합니다.</p>

<p><img src="/assets/images/2026-04-11-ocioke/oke_remove_seclist.jpeg" alt="oke_remove_seclist" /></p>

<p>이제 불필요한 기존 시큐리티 리스트는 오른쪽 점세개 버튼을 클릭하여 REMOVE로 제거합니다.</p>

<p><img src="/assets/images/2026-04-11-ocioke/oke_remove_seclist2.jpeg" alt="oke_remove_seclist2" /></p>

<p>다시 VCN의 Security 탭으로 돌아와서 불필요해진 Security List는 Terminate로 리소스 자체를 삭제합니다.</p>

<p><img src="/assets/images/2026-04-11-ocioke/oke_remove_routetable.jpeg" alt="oke_remove_routetable" /></p>

<p>VCN의 Routing 탭에서 불필요해진 Route Table 역시 리소스 자체를 삭제합니다.</p>

<p>저는 DMZ Subnet도 깔끔하게 정리하고 싶어서, 마찬가지로 라우트 테이블 생성, 시큐리티 리스트 생성을 진행하고 기존의 리소스 들은 정리해 줬습니다.</p>

<p>기존의 security list와 route table에 등록된 룰도 확인하여 동일하게 적용해주었습니다. (VCN의 default route table과 security list는 삭제할 수 없어 리소스 자체를 Terminate 하지는 않았습니다.)</p>

<p><br /></p>

<h4 id="route-table-규칙-추가">Route Table 규칙 추가</h4>

<p><br /></p>

<p>이제 생성된 Route Table에 규칙을 추가하겠습니다.</p>

<p><img src="/assets/images/2026-04-11-ocioke/add_route_rules.jpeg" alt="add_route_rules" /></p>

<p>VCN의 Route 메뉴에서 규칙을 수정할 Route Table을 클릭한 뒤 Route Rules 메뉴에 들어가서, Add Route Rules 버튼을 클릭하여 규칙을 추가합니다.</p>

<p><img src="/assets/images/2026-04-11-ocioke/add_route_rules2.jpeg" alt="add_route_rules2" /></p>

<p>Route Target Type, Destination CIDR Block, Description 등을 선택하고 Save 버튼을 클릭하여 규칙을 추가합니다.</p>

<p>아래 표와 같이 나머지 규칙들도 추가해주겠습니다.</p>

<table>
  <thead>
    <tr>
      <th style="text-align: center">Route Table</th>
      <th style="text-align: center">Destination</th>
      <th style="text-align: center">Target Type</th>
      <th style="text-align: center">Target</th>
      <th style="text-align: center">Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: center">KUBERNETES_APIENDPOINTS_RouteTable</td>
      <td style="text-align: center">0.0.0.0/0</td>
      <td style="text-align: center">NAT Gateway</td>
      <td style="text-align: center">-</td>
      <td style="text-align: center">Rule for traffic to internet</td>
    </tr>
    <tr>
      <td style="text-align: center">KUBERNETES_APIENDPOINTS_RouteTable</td>
      <td style="text-align: center">All <region> Services in Oracle Services Network</region></td>
      <td style="text-align: center">Service Gateway</td>
      <td style="text-align: center">-</td>
      <td style="text-align: center">Rule for traffic to OCI services</td>
    </tr>
  </tbody>
</table>

<p><br /></p>

<p><img src="/assets/images/2026-04-11-ocioke/route_rules.jpeg" alt="route_rules" /></p>

<p>API ENDPOINTS Route Rule은 위와 같이 설정되었고, 나머지 라우트 테이블에 대해서도 같은 방식으로 규칙을 추가해줍니다.</p>

<table>
  <thead>
    <tr>
      <th style="text-align: center">Route Table</th>
      <th style="text-align: center">Destination</th>
      <th style="text-align: center">Target Type</th>
      <th style="text-align: center">Target</th>
      <th style="text-align: center">Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: center">KUBERNETES_WORKERNODES_RouteTable</td>
      <td style="text-align: center">All <region> Services in Oracle Services Network</region></td>
      <td style="text-align: center">Service Gateway</td>
      <td style="text-align: center">-</td>
      <td style="text-align: center">Rule for traffic to OCI services</td>
    </tr>
  </tbody>
</table>

<p><br /></p>

<table>
  <thead>
    <tr>
      <th style="text-align: center">Route Table</th>
      <th style="text-align: center">Destination</th>
      <th style="text-align: center">Target Type</th>
      <th style="text-align: center">Target</th>
      <th style="text-align: center">Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: center">KUBERNETES_PODS_RouteTable</td>
      <td style="text-align: center">0.0.0.0/0</td>
      <td style="text-align: center">NAT Gateway</td>
      <td style="text-align: center">-</td>
      <td style="text-align: center">Rule for traffic to internet</td>
    </tr>
    <tr>
      <td style="text-align: center">KUBERNETES_PODS_RouteTable</td>
      <td style="text-align: center">All <region> Services in Oracle Services Network</region></td>
      <td style="text-align: center">Service Gateway</td>
      <td style="text-align: center">-</td>
      <td style="text-align: center">Rule for traffic to OCI services</td>
    </tr>
  </tbody>
</table>

<p><br /></p>

<table>
  <thead>
    <tr>
      <th style="text-align: center">Route Table</th>
      <th style="text-align: center">Destination</th>
      <th style="text-align: center">Target Type</th>
      <th style="text-align: center">Target</th>
      <th style="text-align: center">Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: center">KUBERNETES_LOADBALANCERS_RouteTable</td>
      <td style="text-align: center">0.0.0.0/0</td>
      <td style="text-align: center">Internet Gateway</td>
      <td style="text-align: center">-</td>
      <td style="text-align: center">Rule for traffic to internet</td>
    </tr>
  </tbody>
</table>

<p><br /></p>

<h4 id="security-list-규칙-추가">Security List 규칙 추가</h4>

<p><br /></p>

<p>Route Table과 유사한 방식으로 Security List에도 규칙을 추가합니다.</p>

<p><img src="/assets/images/2026-04-11-ocioke/add_security_rules.jpeg" alt="add_security_rules" /></p>

<p>VCN의 Security 탭으로 가서 규칙을 추가할 Security List를 클릭하고, Security rules 버튼을 클릭한 후, “Add Ingress Rules” 또는 “Add Egress Rules” 버튼을 클릭하여 규칙을 추가합니다.</p>

<p><img src="/assets/images/2026-04-11-ocioke/add_security_rules2.jpeg" alt="add_security_rules2" /></p>

<p>Security Rule을 추가하기 위한 Source CIDR, Protocol, Destination Port, Description 등을 입력후 “Add Rules” 버튼을 클릭하여 규칙을 추가합니다.</p>

<p>마찬가지 방식으로 아래의 룰을 모두 추가합니다.</p>

<p><br /></p>

<table>
  <thead>
    <tr>
      <th>Security List</th>
      <th>Type</th>
      <th>State:</th>
      <th>Source</th>
      <th>Protocol / Dest. Port</th>
      <th>Description:</th>
      <th> </th>
      <th> </th>
      <th> </th>
      <th> </th>
      <th> </th>
      <th> </th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>KUBERNETES_APIENDPOINTS_SecurityList</td>
      <td>Ingress Rules</td>
      <td>Stateful</td>
      <td>10.0.1.0/24 (Worker Nodes CIDR)</td>
      <td>TCP/6443</td>
      <td>Kubernetes worker to Kubernetes API endpoint communication.</td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
    <tr>
      <td>KUBERNETES_APIENDPOINTS_SecurityList</td>
      <td>Ingress Rules</td>
      <td>Stateful</td>
      <td>10.0.1.0/24 (Worker Nodes CIDR)</td>
      <td>TCP/12250</td>
      <td>Kubernetes worker to Kubernetes API endpoint communication.</td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
    <tr>
      <td>KUBERNETES_APIENDPOINTS_SecurityList</td>
      <td>Ingress Rules</td>
      <td>Stateful</td>
      <td>10.0.1.0/24 (Worker Nodes CIDR)</td>
      <td>ICMP 3,4</td>
      <td>Path Discovery.</td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
    <tr>
      <td>KUBERNETES_APIENDPOINTS_SecurityList</td>
      <td>Ingress Rules</td>
      <td>Stateful</td>
      <td>10.0.32.0/19 (Pods CIDR)</td>
      <td>TCP/6443</td>
      <td>Pod to Kubernetes API endpoint communication (when using VCN-native pod networking).</td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
    <tr>
      <td>KUBERNETES_APIENDPOINTS_SecurityList</td>
      <td>Ingress Rules</td>
      <td>Stateful</td>
      <td>10.0.32.0/19 (Pods CIDR)</td>
      <td>TCP/12250</td>
      <td>Pod to Kubernetes API endpoint communication (when using VCN-native pod networking).</td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
    <tr>
      <td>KUBERNETES_APIENDPOINTS_SecurityList</td>
      <td>Ingress Rules</td>
      <td>Stateful</td>
      <td>10.0.0.0/24 (Bastions)</td>
      <td>TCP/6443</td>
      <td>(optional) External access to Kubernetes API endpoint.</td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
    <tr>
      <td>KUBERNETES_APIENDPOINTS_SecurityList</td>
      <td>Egress Rules</td>
      <td>Stateful</td>
      <td>All <region> Services in Oracle Services Network</region></td>
      <td>TCP/ALL</td>
      <td>Allow Kubernetes API endpoint to communicate with OKE.</td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
    <tr>
      <td>KUBERNETES_APIENDPOINTS_SecurityList</td>
      <td>Egress Rules</td>
      <td>Stateful</td>
      <td>All <region> Services in Oracle Services Network</region></td>
      <td>ICMP 3,4</td>
      <td>Path Discovery.</td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
    <tr>
      <td>KUBERNETES_APIENDPOINTS_SecurityList</td>
      <td>Egress Rules</td>
      <td>Stateful</td>
      <td>10.0.1.0/24 (Worker Nodes CIDR)</td>
      <td>TCP/10250</td>
      <td>Allow Kubernetes API endpoint to communicate with worker nodes.</td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
    <tr>
      <td>KUBERNETES_APIENDPOINTS_SecurityList</td>
      <td>Egress Rules</td>
      <td>Stateful</td>
      <td>10.0.1.0/24 (Worker Nodes CIDR)</td>
      <td>ICMP 3,4</td>
      <td>Path Discovery.</td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
    <tr>
      <td>KUBERNETES_APIENDPOINTS_SecurityList</td>
      <td>Egress Rules</td>
      <td>Stateful</td>
      <td>10.0.32.0/19 (Pods CIDR)</td>
      <td>ALL/ALL</td>
      <td>Allow Kubernetes API endpoint to communicate with pods.</td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
  </tbody>
</table>

<p><br /></p>

<p><img src="/assets/images/2026-04-11-ocioke/security_rules.jpeg" alt="security_rules" /></p>

<p>비슷한 방식으로 아래의 다른 규칙들도 추가해줍니다.</p>

<table>
  <thead>
    <tr>
      <th>Security List</th>
      <th>Type</th>
      <th>State:</th>
      <th>Source</th>
      <th>Protocol / Dest. Port</th>
      <th>Description:</th>
      <th> </th>
      <th> </th>
      <th> </th>
      <th> </th>
      <th> </th>
      <th> </th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>KUBERNETES_WORKERNODES_SecurityList</td>
      <td>Ingress Rules</td>
      <td>Stateful</td>
      <td>10.0.3.0/29 (Kubernetes API Endpoint CIDR)</td>
      <td>TCP/10250</td>
      <td>Allow Kubernetes API endpoint to communicate with worker nodes.</td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
    <tr>
      <td>KUBERNETES_WORKERNODES_SecurityList</td>
      <td>Ingress Rules</td>
      <td>Stateful</td>
      <td>0.0.0.0/0</td>
      <td>ICMP 3,4</td>
      <td>Path Discovery.</td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
    <tr>
      <td>KUBERNETES_WORKERNODES_SecurityList</td>
      <td>Ingress Rules</td>
      <td>Stateful</td>
      <td>10.0.0.0/24 (Bastions)</td>
      <td>TCP/22</td>
      <td>(optional) Allow inbound SSH traffic to managed nodes.</td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
    <tr>
      <td>KUBERNETES_WORKERNODES_SecurityList</td>
      <td>Ingress Rules</td>
      <td>Stateful</td>
      <td>10.0.2.0/24 (Load balancer subnet CIDR)</td>
      <td>ALL/30000-32767</td>
      <td>Load balancer to worker nodes node ports.</td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
    <tr>
      <td>KUBERNETES_WORKERNODES_SecurityList</td>
      <td>Ingress Rules</td>
      <td>Stateful</td>
      <td>10.0.2.0/24 (Load balancer subnet CIDR)</td>
      <td>ALL/10256</td>
      <td>Allow load balancer to communicate with kube-proxy on worker nodes.</td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
    <tr>
      <td>KUBERNETES_WORKERNODES_SecurityList</td>
      <td>Egress Rules</td>
      <td>Stateful</td>
      <td>10.0.32.0/19 (Pods CIDR)</td>
      <td>ALL/ALL</td>
      <td>Allow worker nodes to access pods.</td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
    <tr>
      <td>KUBERNETES_WORKERNODES_SecurityList</td>
      <td>Egress Rules</td>
      <td>Stateful</td>
      <td>0.0.0.0/0</td>
      <td>ICMP 3,4</td>
      <td>Path Discovery.</td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
    <tr>
      <td>KUBERNETES_WORKERNODES_SecurityList</td>
      <td>Egress Rules</td>
      <td>Stateful</td>
      <td>All <region> Services in Oracle Services Network</region></td>
      <td>TCP/ALL</td>
      <td>Allow worker nodes to communicate with OKE.</td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
    <tr>
      <td>KUBERNETES_WORKERNODES_SecurityList</td>
      <td>Egress Rules</td>
      <td>Stateful</td>
      <td>10.0.3.0/29 (Kubernetes API Endpoint CIDR)</td>
      <td>TCP/6443</td>
      <td>Kubernetes worker to Kubernetes API endpoint communication.</td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
    <tr>
      <td>KUBERNETES_WORKERNODES_SecurityList</td>
      <td>Egress Rules</td>
      <td>Stateful</td>
      <td>10.0.3.0/29 (Kubernetes API Endpoint CIDR)</td>
      <td>TCP/12250</td>
      <td>Kubernetes worker to Kubernetes API endpoint communication.</td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
  </tbody>
</table>

<p><br /></p>

<table>
  <thead>
    <tr>
      <th>Security List</th>
      <th>Type</th>
      <th>State:</th>
      <th>Source</th>
      <th>Protocol / Dest. Port</th>
      <th>Description:</th>
      <th> </th>
      <th> </th>
      <th> </th>
      <th> </th>
      <th> </th>
      <th> </th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>KUBERNETES_PODS_SecurityList</td>
      <td>Ingress Rules</td>
      <td>Stateful</td>
      <td>10.0.1.0/24 (Worker Nodes CIDR)</td>
      <td>ALL/ALL</td>
      <td>Allow worker nodes to access pods.</td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
    <tr>
      <td>KUBERNETES_PODS_SecurityList</td>
      <td>Ingress Rules</td>
      <td>Stateful</td>
      <td>10.0.3.0/29 (Kubernetes API Endpoint CIDR)</td>
      <td>ALL/ALL</td>
      <td>Allow Kubernetes API endpoint to communicate with pods.</td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
    <tr>
      <td>KUBERNETES_PODS_SecurityList</td>
      <td>Ingress Rules</td>
      <td>Stateful</td>
      <td>10.0.32.0/19 (Pods CIDR)</td>
      <td>ALL/ALL</td>
      <td>Allow pods to communicate with other pods.</td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
    <tr>
      <td>KUBERNETES_PODS_SecurityList</td>
      <td>Egress Rules</td>
      <td>Stateful</td>
      <td>10.0.32.0/19 (Pods CIDR)</td>
      <td>ALL/ALL</td>
      <td>Allow pods to communicate with other pods.</td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
    <tr>
      <td>KUBERNETES_PODS_SecurityList</td>
      <td>Egress Rules</td>
      <td>Stateful</td>
      <td>All <region> Services in Oracle Services Network</region></td>
      <td>ICMP 3,4</td>
      <td>Path Discovery.</td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
    <tr>
      <td>KUBERNETES_PODS_SecurityList</td>
      <td>Egress Rules</td>
      <td>Stateful</td>
      <td>All <region> Services in Oracle Services Network</region></td>
      <td>TCP/ALL</td>
      <td>Allow pods to communicate with OCI services.</td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
    <tr>
      <td>KUBERNETES_PODS_SecurityList</td>
      <td>Egress Rules</td>
      <td>Stateful</td>
      <td>0.0.0.0/0</td>
      <td>TCP/443</td>
      <td>(optional) Allow pods to communicate with internet.</td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
    <tr>
      <td>KUBERNETES_PODS_SecurityList</td>
      <td>Egress Rules</td>
      <td>Stateful</td>
      <td>10.0.3.0/29 (Kubernetes API Endpoint CIDR)</td>
      <td>TCP/6443</td>
      <td>Pod to Kubernetes API endpoint communication (when using VCN-native pod networking).</td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
    <tr>
      <td>KUBERNETES_PODS_SecurityList</td>
      <td>Egress Rules</td>
      <td>Stateful</td>
      <td>10.0.3.0/29 (Kubernetes API Endpoint CIDR)</td>
      <td>TCP/12250</td>
      <td>Pod to Kubernetes API endpoint communication (when using VCN-native pod networking).</td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
  </tbody>
</table>

<p><br /></p>

<table>
  <thead>
    <tr>
      <th>Security List</th>
      <th>Type</th>
      <th>State:</th>
      <th>Source</th>
      <th>Protocol / Dest. Port</th>
      <th>Description:</th>
      <th> </th>
      <th> </th>
      <th> </th>
      <th> </th>
      <th> </th>
      <th> </th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>KUBERNETES_LOADBALANCERS_SecurityList</td>
      <td>Ingress Rules</td>
      <td>Stateful</td>
      <td>0.0.0.0/0</td>
      <td>TCP / 80, 443</td>
      <td>(optional) Load balancer listener protocol and port. Customize as required.</td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
    <tr>
      <td>KUBERNETES_LOADBALANCERS_SecurityList</td>
      <td>Egress Rules</td>
      <td>Stateful</td>
      <td>10.0.1.0/24 (Worker Nodes CIDR)</td>
      <td>ALL/30000-32767</td>
      <td>Load balancer to worker nodes node ports.</td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
    <tr>
      <td>KUBERNETES_LOADBALANCERS_SecurityList</td>
      <td>Egress Rules</td>
      <td>Stateful</td>
      <td>10.0.1.0/24 (Worker Nodes CIDR)</td>
      <td>ALL/10256</td>
      <td>Allow load balancer to communicate with kube-proxy on worker nodes.</td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
  </tbody>
</table>

<p><br /></p>

<table>
  <thead>
    <tr>
      <th>Security List</th>
      <th>Type</th>
      <th>State:</th>
      <th>Source</th>
      <th>Protocol / Dest. Port</th>
      <th>Description:</th>
      <th> </th>
      <th> </th>
      <th> </th>
      <th> </th>
      <th> </th>
      <th> </th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>DMZ_SecurityList</td>
      <td>Egress Rules</td>
      <td>Stateful</td>
      <td>10.0.3.0/29 (Kubernetes API Endpoint CIDR)</td>
      <td>TCP/6443</td>
      <td>(optional) Allow bastion to access the Kubernetes API endpoint.</td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
    <tr>
      <td>DMZ_SecurityList</td>
      <td>Egress Rules</td>
      <td>Stateful</td>
      <td>10.0.1.0/24 (Worker Nodes CIDR)</td>
      <td>TCP/22</td>
      <td>(optional) Allow SSH traffic to worker nodes.</td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
      <td> </td>
    </tr>
  </tbody>
</table>

<p><br /></p>

<h1 id="private-oke-클러스터-생성">Private OKE 클러스터 생성</h1>

<p><br /></p>

<p>위의 복잡한 네트워크 구성이 모두 끝났다면 이제 본격적으로 OKE 클러스터 자원을 생성합니다.</p>

<p><img src="/assets/images/2026-04-11-ocioke/oke_menu.jpeg" alt="oke_menu" /></p>

<p>OCI 전체 메뉴에서 Developer Services 섹션에 있는 Kubernetes Clusters(OKE) 메뉴를 클릭합니다.</p>

<p><img src="/assets/images/2026-04-11-ocioke/oke_create.jpeg" alt="oke_create" /></p>

<p>컴파트먼트가 올바르게 선택 되었는지 확인 후, “Create Cluster” 버튼을 클릭하고, 이어지는 화면에서 Custom create를 클릭하고 Proceed 버튼을 클릭합니다.</p>

<p><img src="/assets/images/2026-04-11-ocioke/oke_create2.jpeg" alt="oke_create2" /></p>

<p>쿠버네티스 클러스터의 이름과 버전을 선택 후, Next를 클릭하여 다음 페이지로 이동합니다.</p>

<p><img src="/assets/images/2026-04-11-ocioke/oke_create3.jpeg" alt="oke_create3" /></p>

<p><img src="/assets/images/2026-04-11-ocioke/oke_create4.jpeg" alt="oke_create4" /></p>

<p>네트워크 타입을 “VCN-native pod networking”으로 선택 후, VCN과 API endpoint로 사용할 서브넷을 선택하고, Load balancer 용도로 사용할 서브넷도 명시한 뒤, Next로 다음 페이지로 이동합니다.</p>

<p><img src="/assets/images/2026-04-11-ocioke/oke_create5.jpeg" alt="oke_create5" /></p>

<p>Nodepool의 이름을 명명하고, 무료로 사용하기 위해서 Node type은 Managed를 선택합니다.</p>

<p><img src="/assets/images/2026-04-11-ocioke/oke_create6.jpeg" alt="oke_create6" /></p>

<p><img src="/assets/images/2026-04-11-ocioke/oke_create7.jpeg" alt="oke_create7" /></p>

<p>AD, FD와 Nodepool이 사용할 서브넷을 선택하고, Node가 사용할 shape와 이미지를 선택합니다.</p>

<p>무료로 사용하기 위해서, A1.Flex Shape을 사용하고, 2개 노드를 운영하기 위해서 각 노드는 2OCPU, 12GB Memory를 사용하도록 설정하였고, OS는 Oracle Linux를 그대로 사용하기로 하였습니다.</p>

<p>아래쪽에 등장하는 Node count 값은 2로 설정해줍니다.</p>

<p><img src="/assets/images/2026-04-11-ocioke/oke_create8.jpeg" alt="oke_create8" /></p>

<p>Pod communication에서는 POD가 사용할 서브넷을 선택한 후, Next를 클릭하여 다음 설정으로 넘어갑니다.</p>

<p><img src="/assets/images/2026-04-11-ocioke/oke_create9.jpeg" alt="oke_create9" /></p>

<p>마지막으로 선택된 옵션들을 검토하고, 잘못된 내용이 없다면 Create_cluster를 클릭하여 OKE 클러스터를 생성합니다.</p>

<p>지금처럼 무료로 쿠버네티스 클러스터를 운영하기 위해서 A1.Flex 같은 SHAPE를 선택한 경우에는 NODE POOL을 생성할때 더이상 생성할 자원이 OCI 쪽에 없어서 NODE POOL CREATE가 실패하고 계속 NODEPOOL_RECONCILE Work Request가 쌓이게 되는데, 이것은 지속적으로 OCI에서 반복해서 생성 요청을 하는 것 같고, 조금 시간이 지나면 생성이 완료되는 것 같습니다.</p>

<p><img src="/assets/images/2026-04-11-ocioke/oke_create10.jpeg" alt="oke_create10" /></p>

<p>며칠정도 시간이 지나면 위 이미지와 같이 클러스터와 노드풀 모두 성공적으로 생성되어 Active 상태로 남아있게 되는 것을 확인할 수 있습니다.</p>

<p><img src="/assets/images/2026-04-11-ocioke/mlplatform_network2.jpeg" alt="mlplatformnetwork2" /></p>

<p>최종적으로 위 이미지와 같은 네트워크가 구성되었습니다.</p>

<p>다음으로는 구성된 클러스터 위에 서비스를 배포해 보겠습니다.</p>]]></content><author><name>Juyoung Hong</name><email>hjy_stat@naver.com</email></author><category term="infra" /><category term="oracle-cloud" /><category term="oke" /><category term="kubernetes" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">오라클 클라우드에 무료 bastion 서버 구성하기</title><link href="https://juyoung-hong.github.io/infra/ocibastion/" rel="alternate" type="text/html" title="오라클 클라우드에 무료 bastion 서버 구성하기" /><published>2026-03-31T00:00:00+09:00</published><updated>2026-03-31T00:00:00+09:00</updated><id>https://juyoung-hong.github.io/infra/ocibastion</id><content type="html" xml:base="https://juyoung-hong.github.io/infra/ocibastion/"><![CDATA[<p><br /></p>

<h1 id="오라클-클라우드에-무료-bastion-서버-구성하기">오라클 클라우드에 무료 bastion 서버 구성하기</h1>

<p><br /></p>

<p>오늘은 아래의 지난 글에 이어서 오라클 클라우드에 배치할 클라우드 리소스들과 통신하기 위한 bastion 서버를 구성해보겠습니다.</p>

<ul>
  <li>오라클 클라우드로 무료 인프라 네트워크 구성하기: <a href="https://juyoung-hong.github.io/infra/ocinetwork/">링크</a></li>
</ul>

<p><br /></p>

<h2 id="bastion">Bastion</h2>

<p><br /></p>

<p>Bastion Host는 외부 네트워크 (인터넷)에서 사설 네트워크(내부)로 접근할 때 거치는 중계 서버로써 외부 공격을 차단하는 요새 역할을 하며, SSH 접속을 단일화하여 보안을 강화하고, 내부 서버의 접근 제어를 수행합니다.</p>

<p>OCI에서는 별도의 Bastion 서버를 두지 않아도 Bastion 서비스를 이용하여 사설 망에 있는 서버에 접속할 수 있지만, 별도의 서버가 없다면 매번 Bastion 리소스를 생성해야하는 번거로움이 있고, 향후 CI/CD용 서버로도 사용할 예정이기 때문에 Bastion 서버를 구성해보겠습니다.</p>

<p><br /></p>

<h1 id="가상머신-생성">가상머신 생성</h1>

<p><br /></p>

<p><img src="/assets/images/2026-03-31-ocibastion/oci_compute_menu.jpeg" alt="ocicomputemenu" /></p>

<p>OCI 전체 메뉴의 Compute를 클릭하고, Instance를 클릭하여 메뉴로 진입합니다.</p>

<p><img src="/assets/images/2026-03-31-ocibastion/oci_compute_main.jpeg" alt="ocicomputemain" /></p>

<p>메인 메뉴에 진입하여 compartment가 맞게 설정되었는지 확인하고, “Create instance” 버튼을 클릭하여 가상머신 생성 페이지로 이동합니다.</p>

<p><img src="/assets/images/2026-03-31-ocibastion/oci_compute_create.jpeg" alt="ocicomputecreate" /></p>

<p>생성할 가상머신의 이름을 입력합니다. 네이밍 룰이 필요하며, 저는 직관적으로 {PRD/DEV}_{Application}으로 작성하였습니다.</p>

<p><img src="/assets/images/2026-03-31-ocibastion/oci_compute_create2.jpeg" alt="ocicomputecreate2" /></p>

<p>아래로 내리다 보면 Image가 있고 기본적으로 Oracle Linux가 선택되어 있습니다.</p>

<p>오라클 리눅스도 훌륭하지만 낮은 성능의 VM에서 메모리를 많이 잡아먹는 경향이 있기에 변경하고자 합니다.</p>

<p>Change Image 버튼을 클릭합니다.</p>

<p><img src="/assets/images/2026-03-31-ocibastion/oci_compute_create3.jpeg" alt="ocicomputecreate3" /></p>

<p>요즘 가상 많이 사용하는 Ubuntu를 선택한 뒤, 아래로 내려려 최신 이미지이면서 리소스를 조금만 사용할 수 있는 Ubuntu 24.04 Minimal을 선택하고 Select Image 버튼을 클릭합니다.</p>

<p><img src="/assets/images/2026-03-31-ocibastion/oci_compute_create4.jpeg" alt="ocicomputecreate4" /></p>

<p>마찬가지로 Shape를 변경하겠습니다. Change Shape 버튼을 클릭합니다.</p>

<p><img src="/assets/images/2026-03-31-ocibastion/oci_compute_create5.jpeg" alt="ocicomputecreate5" /></p>

<p>저는 항상 무료인 VM을 만들 예정이므로, Virtual machine을 선택하고, Specialty and previous generation을 선택하겠습니다.</p>

<p>Always Free-eligible 딱지가 붙어있는 VM.Standard.E2.1.Micro Shape를 선택하고, Select Shape 버튼을 클릭합니다.</p>

<p><img src="/assets/images/2026-03-31-ocibastion/oci_compute_create6.jpeg" alt="ocicomputecreate6" /></p>

<p>구성된 내용이 맞는지 확인하고, 별도로 Adbanced Option은 없이 Next를 클릭합니다.</p>

<p><img src="/assets/images/2026-03-31-ocibastion/oci_compute_create7.jpeg" alt="ocicomputecreate7" /></p>

<p>Secutiry Option을 선택할 수 있지만 잘 모르는 옵션이므로 선택하지 않고 Next를 클릭하여 진행하겠습니다.</p>

<p><img src="/assets/images/2026-03-31-ocibastion/oci_compute_create8.jpeg" alt="ocicomputecreate8" /></p>

<p>Networking 부분에서는 우선 VNIC 이름을 입력합니다. 네이밍룰은 {DEV/PRD}_{Application}_VNIC로 작성하였습니다.</p>

<p>Network 및 Subnet은 이전에 생성한 자원을 사용하게끔 설정하였고, Public Subnet인 DMZ_Subnet에 생성될 수 있도록 선택하였습니다.</p>

<p><br /></p>

<h2 id="ssh-key-생성">SSH Key 생성</h2>

<p><br /></p>

<p>SSH 접속에 사용할 Key는 새로 내려받아도 되지만 키를 소중히 관리해야하고, 가끔 Key에 문제가 생기는 경우가 있었던 것 같아서 로컬에서 만들어서 pub key를 업로드 하는 방식으로 이용하겠습니다.</p>

<p>아래의 명령어를 노트북의 터미널에서 실행하여 ssh key를 생성합니다.</p>

<div class="language-zsh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh-keygen <span class="nt">-t</span> rsa <span class="nt">-b</span> 2048 <span class="nt">-f</span> ~/.ssh/prd_oci
</code></pre></div></div>

<p><img src="/assets/images/2026-03-31-ocibastion/ssh-key-gen.jpeg" alt="sshkeygen" /></p>

<p>private key, public key가 생성된 이후에는 마찬가지로 터미널에서 아래 명령어를 수행하여 생성된 pub 키를 출력하고, 출력된 키를 복사합니다 (ssh-rsa부터 .local 등 마지막까지)</p>

<div class="language-zsh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cat</span> .ssh/prd_oci.pub
</code></pre></div></div>

<p><img src="/assets/images/2026-03-31-ocibastion/oci_compute_create9.jpeg" alt="ocicomputecreate9" /></p>

<p>다시 OCI 콘솔로 돌아와서, Paste public key를 선택한 뒤, 터미널에서 복사한 public key를 붙여넣기하고 Next 버튼을 클릭합니다.</p>

<p><img src="/assets/images/2026-03-31-ocibastion/oci_compute_create10.jpeg" alt="ocicomputecreate10" /></p>

<p>다음으로 부트 볼륨을 선택하는데, 이부분도 기본 옵션을 유지한채로 Next를 클릭합니다.</p>

<p><img src="/assets/images/2026-03-31-ocibastion/oci_compute_create11.jpeg" alt="ocicomputecreate11" /></p>

<p>마지막으로 잘못된 부분이 없는지 검토한 뒤, Create 버튼을 클릭하여 생성을 완료합니다.</p>

<p>이후 VM 상세 페이지로 이동하며 조금 기다리면 프로비저닝이 완료되고, Running 상태로 VM이 활성화 됩니다.</p>

<p><br /></p>

<h1 id="bastion-방화벽-설정">Bastion 방화벽 설정</h1>

<p><br /></p>

<p>Bastion은 모든 서버의 관문 역할을 할 예정이므로 본인만 접속할 수 있도록 철저하게 방화벽을 등록합니다.</p>

<p><img src="/assets/images/2026-03-31-ocibastion/oci_firewall.jpeg" alt="ocifirewall" /></p>

<p>Networking 메뉴의 Virtual cloud networks에서 생성된 VCN (PRD_MLPLATFORM_VCN)을 선택한 뒤, Subnet에서 Bastion 서버가 위치한 서브넷인 DMZ_Subnet을 클릭합니다.</p>

<p><img src="/assets/images/2026-03-31-ocibastion/oci_security.jpeg" alt="ocisecurity" /></p>

<p>Subnet에서는 Security를 클릭하여, 기본적으로 구성된 security list를 클릭합니다.</p>

<p><img src="/assets/images/2026-03-31-ocibastion/oci_securitylist.jpeg" alt="ocisecuritylist" /></p>

<p>기본적으로 public subnet에서는 모든 곳에서 22번 포트로 통신이 가능하게끔 ingress rule이 설정되어 있습니다.</p>

<p>오른쪽 점세개를 클릭하여 Edit 버튼을 클릭하고 이부분은 저만 들어올 수 있도록 수정합니다.</p>

<p><img src="/assets/images/2026-03-31-ocibastion/oci_securitylist2.jpeg" alt="ocisecuritylist2" /></p>

<p><a href="https://ip.pe.kr/">내 아이피확인</a> 사이트에 접속해서 자택의 IP 주소를 확인합니다.</p>

<p>Source IP를 0.0.0.0/0 대신 위에서 확인한 IP주소/32로 입력하고, 이 규칙이 어떤 규칙인지 확인이 쉽도록 Description을 입력한 뒤, save changes 버튼을 클릭하여 저장합니다.</p>

<p><br /></p>

<h1 id="bastion-서버-ssh-접속">Bastion 서버 SSH 접속</h1>

<p><br /></p>

<p>이제 다시 Bastion 서버로 돌아와서, 상세 페이지를 조금 내려보면 Bastion 서버에 할당된 Public IP Address를 확인할 수 있습니다.</p>

<p><img src="/assets/images/2026-03-31-ocibastion/oci_bastion_main.jpeg" alt="ocibastionmain" /></p>

<p>이 값을 확인하고 VSCODE 등 IDE에서 쉽게 접속할 수 있도록 원격 접속 도구에서 아래와 같이 입력합니다.</p>

<p><img src="/assets/images/2026-03-31-ocibastion/vscode_ssh.jpeg" alt="vscodessh" /></p>

<p>VSCODE의 REMOTE-SSH 확장 프로그램은 ~/.ssh/config 파일로 이 값을 관리하며, 아래와 같이 bastion 관련 설정값을 입력 후 저장합니다.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Host bastion
  HostName 146.56.106.229
  User ubuntu
  IdentityFile /Users/jyhong/.ssh/prd_oci
</code></pre></div></div>

<p><img src="/assets/images/2026-03-31-ocibastion/vscode_ssh2.jpeg" alt="vscodessh2" /></p>

<p>이제 REMOTE-SSH 실행시에 bastion을 목록에서 확인할 수 있고, 클릭하면 bastion 장비에 접속합니다.</p>

<p>최초 접속시 입력하는 창이 나온다면 yes 입력 후 엔터를 입력하면 VSCode Server를 bastion 서버에서 내려받고 잠시 뒤 서버에 연결됩니다.</p>

<p><img src="/assets/images/2026-03-31-ocibastion/ssh-bastion.jpeg" alt="sshbastion" /></p>

<p>마지막으로 Bastion 서버가 추가됨으로써 아래와 같이 인프라가 구성되었습니다.</p>

<p><img src="/assets/images/2026-03-31-ocibastion/oci_infra_20260331.jpeg" alt="ociinfra" /></p>]]></content><author><name>Juyoung Hong</name><email>hjy_stat@naver.com</email></author><category term="infra" /><category term="oracle-cloud" /><category term="bastion" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">오라클 클라우드로 무료 인프라 네트워크 구성하기</title><link href="https://juyoung-hong.github.io/infra/ocinetwork/" rel="alternate" type="text/html" title="오라클 클라우드로 무료 인프라 네트워크 구성하기" /><published>2026-03-29T00:00:00+09:00</published><updated>2026-03-29T00:00:00+09:00</updated><id>https://juyoung-hong.github.io/infra/ocinetwork</id><content type="html" xml:base="https://juyoung-hong.github.io/infra/ocinetwork/"><![CDATA[<p><br /></p>

<h1 id="오라클-클라우드로-무료-인프라-네트워크-구성하기">오라클 클라우드로 무료 인프라 네트워크 구성하기</h1>

<p><br /></p>

<p>오라클 클라우드는 개인에게도 상당히 많은 양의 리소스를 제공합니다.</p>

<p>클라우드 인프라에 대해서 학습하거나, 개인용 서버를 운영하기에 적합한 환경이므로 오라클 클라우드의 OKE를 구성하여 무료 관리형 쿠버네티스 인프라를 구성해보겠습니다.</p>

<p><br /></p>

<h2 id="오라클-클라우드-회원가입">오라클 클라우드 회원가입</h2>

<p><br /></p>

<p><img src="/assets/images/2026-03-29-ocinetwork/oci_signin_20260329.jpeg" alt="ocisignin" /></p>

<p>가장 먼저 오라클 클라우드 홈페이지에서 회원가입을 진행합니다.</p>

<p><a href="https://www.oracle.com/kr/cloud/">오라클 클라우드 홈페이지</a>에 접속한 뒤, 화면 우측 상단의 사람 버튼을 클릭한 뒤 나오는 화면에서 “무료 클라우드 티어 가입” 버튼을 클릭하여 회원가입을 진행합니다.</p>

<p>회원가입시 리전을 선택해야 한다면, 물리적으로 위치가 가까운 서울, 춘천을 선택하거나 근처 일본까지 선택하시기를 추천드립니다.</p>

<p>( 서울은 더이상 가상머신 생성 등이 불가하며, 춘천도 거의 가득찬 상태입니다. 오사카로 조금 멀리 선택하는 것이 가상머신을 만들때 조금 스트레스를 덜 받을 수 있습니다. )</p>

<p><br /></p>

<h3 id="리전">리전</h3>

<p><br /></p>

<p>OCI에서 리전은 클라우드 서비스를 제공하는 물리적인 인프라의 위치입니다. (서울, 춘천, 도쿄, 오사카 등)</p>

<p>당연히 물리적으로 거리가 가까울수록 네트워크 속도 지연이 발생할 가능성이 적기 때문에 서버에 접속할 사용자들과 물리적으로 가까운 리전을 선택하는 것이 좋습니다.</p>

<p><br /></p>

<h2 id="컴파트먼트-생성">컴파트먼트 생성</h2>

<p><br /></p>

<p>회원가입을 잘 마쳤다면, 클라우드 서비스에 로그인하고 가장 먼저 컴파트먼트를 생성합니다.</p>

<p><br /></p>

<h3 id="테넌시">테넌시</h3>

<p><br /></p>

<p>테넌시는 오라클 클라우드 계정에 할당되는 클라우드 자원 관리 공간으로, 주어진 테넌시 안에서 각종 클라우드 자원을 만들고 관리합니다.</p>

<p>보통 회사가 테넌시의 단위가 되며, 테넌시 내에서 사용자들을 만들고, 그룹화 하여 각 그룹에 대해 클라우드 자원을 관리할 수 있는 정책을 부여하여 사용합니다.</p>

<p><br /></p>

<h3 id="도메인">도메인</h3>

<p><br /></p>

<p>처음 클라우드 계정을 생성하게 되면, default 도메인이 자동으로 생성됩니다.</p>

<p>도메인은 유저와 그룹을 효과적으로 관리하기 위해, 업무 요구에 따라 추가적으로 만들어서 관리할 수 있습니다. 이번 실습에서는 실 사용자가 저밖에 없으니, 도메인은 별도로 만들지 않고, default 도메인을 사용하도록 하겠습니다.</p>

<p><br /></p>

<h3 id="컴파트먼트">컴파트먼트</h3>

<p><br /></p>

<p>컴파트먼트는 오라클 클라우드의 기능 중 하나로, 테넌시 내에서 클라우드 자원을 논리적인 그룹으로 나눌 수 있는 기능입니다.</p>

<p>하나의 테넌시 내에서 업무 구분 또는 조직 단위로 나누어 클라우드 자원을 관리하고자 하는 경우 컴파트먼트로 클라우드 자원을 나누어 정책으로 관리할 수 있고, 컴파트먼트는 계층 구조를 가질 수 있습니다.</p>

<p>예를 들어, 개발조직용 컴파트먼트와 운영조직용 컴파트먼트를 나누어 클라우드 자원을 관리할 수도 있습니다.</p>

<p><br /></p>

<h3 id="컴파트먼트-생성-1">컴파트먼트 생성</h3>

<p><br /></p>

<p><img src="/assets/images/2026-03-29-ocinetwork/oci_compartments_menu.jpeg" alt="ocicompartmentsmenu" /></p>

<p>로그인 이후 나타나는 화면에서 좌측 상단의 햄버거 버튼을 클릭하여 전체 메뉴를 확인합니다.</p>

<p>전체 메뉴에서 Identity &amp; Security 메뉴를 클릭하면, Identity 관련 메뉴 하단의 Compartments 메뉴를 발견할 수 있습니다. 해당 메뉴를 클릭하여 이동합니다.</p>

<p><img src="/assets/images/2026-03-29-ocinetwork/oci_compartments_main.jpeg" alt="ocicompartmentsmain" /></p>

<p>compartments 메뉴에 기본적으로 가상 상위 컴파트먼트 개념인 root 컴파트먼트가 만들어져 있습니다.</p>

<p>root 컴파트먼트는 반드시 삭제하면 안되고, 추가로 사용할 컴파트먼트를 만들겠습니다. Create compartment 화면을 클릭합니다.</p>

<p><img src="/assets/images/2026-03-29-ocinetwork/oci_compartments_create.jpeg" alt="ocicompartmentscreate" /></p>

<ol>
  <li>생성할 컴파트먼트의 이름을 작성합니다. 별도의 명명규칙이 있으면 좋을텐데 저는 “{dev/prd}_{application}_compartment”로 사용하겠습니다.</li>
  <li>Description에는 컴파트먼트에 대한 설명을 작성하였습니다.</li>
  <li>Parent comparment는 최상위 컴파트먼트였던 root 컴파트먼트를 선택 후 Create compartment 버튼을 클릭하여 생성합니다.</li>
</ol>

<p>잠시 뒤, compartments 메뉴에서 새로고침을 진행하면 새로운 컴파트먼트가 생성되었음을 확인할 수 있습니다.</p>

<p>앞으로 생성할 ML Platform 관련 리소스들은 해당 컴파트먼트 하위에 생성하겠습니다.</p>

<p><img src="/assets/images/2026-03-29-ocinetwork/oci_compartments_main2.jpeg" alt="ocicompartmentsmain2" /></p>

<p>이제 생성된 컴파트먼트에 유저를 등록하고, 유저 그룹을 만들고 정책을 적용할 수 있는 준비가 되었습니다.</p>

<p>그러나 현재 저는 혼자서 클라우드 자원 관리를 진행하고자 하니 일단 해당 과정은 생략하고 리소스를 만들어보도록 하겠습니다.</p>

<p><br /></p>

<h2 id="가상-클라우드-네트워크-구성">가상 클라우드 네트워크 구성</h2>

<p><br /></p>

<p>다음으로 진행할 일은 클라우드 자원들이 배치되어 서로 통신할 수 있도록 가상 클라우드 네트워크 (VCN)을 만드는 일입니다.</p>

<p><br /></p>

<h3 id="가상-클라우드-네트워크-vcn">가상 클라우드 네트워크 (VCN)</h3>

<p><br /></p>

<p>가상 클라우드 네트워크 (Virtual Cloud Network)는 전통적인 물리 네트워크의 가상화된 버전입니다.</p>

<p>소프트웨어 정의 네트워크 (Software Defined Network)로 구현되며, 서브넷, 라우트 테이블, 게이트웨이 등의 네트워크 장치들도 소프트웨어적으로 정의된 형태로 구성됩니다.</p>

<p>사용자는 오라클 클라우드 데이터센터 내에서 사설 네트워크를 VCN 위에 구성할 수 있습니다.</p>

<p><br /></p>

<h3 id="vcn-생성">VCN 생성</h3>

<p><br /></p>

<p><img src="/assets/images/2026-03-29-ocinetwork/oci_vcn_menu.jpeg" alt="ocivcnmenu" /></p>

<p>오라클 클라우드 전체 메뉴로 이동하여, 이번에는 Networking 탭에 있는 Virtual Cloud Networks 메뉴로 이동합니다.</p>

<p><img src="/assets/images/2026-03-29-ocinetwork/oci_vcn_main.jpeg" alt="ocivcnmain" /></p>

<p>기본적으로 root compartment 하위의 리소스가 나타날텐데, Compartment 쪽을 클릭하여 아까 만든 컴파트먼트가 선택되도록합니다.</p>

<p>컴파트먼트가 잘 선택되었다면 Actions 버튼을 클릭하여 Start VCN Wizard를 클릭합니다.</p>

<p><img src="/assets/images/2026-03-29-ocinetwork/oci_vcn_create.jpeg" alt="ocivcncreate" /></p>

<p>온프레미스 네트워크와 VPN 연결은 필요 없으므로 “Create VCN with Internet Connectivity”를 클릭하고 “Start VCN Wizard” 버튼을 클릭합니다.</p>

<p><img src="/assets/images/2026-03-29-ocinetwork/oci_vcn_create2.jpeg" alt="ocivcncreate2" /></p>

<ol>
  <li>VCN의 이름을 정하는데, 저는 “{dev/prd}_{application}_VCN” 으로 생성하겠습니다.</li>
  <li>Compartment는 위에서 만든 컴파트먼트를 선택해줍니다.</li>
  <li>VCN IPv4 CIDR block은 원하는 사설망 대역이 있다면 변경 가능하지만, 저는 기본 대역으로 생성을 진행하겠습니다.</li>
  <li>이외에도 고급 설정을 적용할 수 있지만 저는 Next 버튼을 클릭하여 생성하려 합니다.</li>
</ol>

<p><img src="/assets/images/2026-03-29-ocinetwork/oci_vcn_create3.jpeg" alt="ocivcncreate3" /></p>

<p>마지막으로 원하는 구성이 맞는지 확인하고, 우측 하단의 Create 버튼을 클릭하여 VCN을 구성합니다.</p>

<p><img src="/assets/images/2026-03-29-ocinetwork/oci_vcn_create4.jpeg" alt="ocivcncreate4" /></p>

<p>조금 기다리면 VCN 생성이 완료되고 우측 하단의 “View VCN” 을 클릭하면 생성된 VCN을 확인할 수 있습니다.</p>

<p><br /></p>

<h2 id="subnet-수정">Subnet 수정</h2>

<p><br /></p>

<p><img src="/assets/images/2026-03-29-ocinetwork/oci_subnet_edit.jpeg" alt="ocivcnsubnetedit" /></p>

<p>생략해도 무방한 절차이지만, 기본적으로 구성된 서브넷과 관련 리소스들의 명명 규칙을 변경하고자 합니다.</p>

<p><img src="/assets/images/2026-03-29-ocinetwork/oci_subnet_edit2.jpeg" alt="ocivcnsubnetedit2" /></p>

<p>Public Subnet은 Load balancer와 bastion 장비 등을 둘 수 있도록 DMZ subnet으로 명명하겠습니다.</p>

<p><img src="/assets/images/2026-03-29-ocinetwork/mlpatform_network.jpeg" alt="mlplatformnetwork" /></p>

<p>최종적으로 위 이미지와 같은 네트워크가 구성되었습니다.</p>

<p>다음으로는 위 네트워크를 좀 더 수정한 뒤, OKE 클러스터를 배포해 보겠습니다.</p>]]></content><author><name>Juyoung Hong</name><email>hjy_stat@naver.com</email></author><category term="infra" /><category term="oracle-cloud" /><category term="network" /><summary type="html"><![CDATA[]]></summary></entry></feed>