<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>be-lgreen.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Sat, 10 Jul 2021 08:37:09 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <copyright>Copyright (C) 2019. be-lgreen.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/be-lgreen" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[쿠버네티스] nodeport vs loadbalancer vs ingress 차이]]></title>
            <link>https://velog.io/@be-lgreen/%EC%BF%A0%EB%B2%84%EB%84%A4%ED%8B%B0%EC%8A%A4-nodeport-vs-loadbalancer-vs-ingress-%EC%B0%A8%EC%9D%B4</link>
            <guid>https://velog.io/@be-lgreen/%EC%BF%A0%EB%B2%84%EB%84%A4%ED%8B%B0%EC%8A%A4-nodeport-vs-loadbalancer-vs-ingress-%EC%B0%A8%EC%9D%B4</guid>
            <pubDate>Sat, 10 Jul 2021 08:37:09 GMT</pubDate>
            <description><![CDATA[<p><a href="https://gmldbd94.tistory.com/148">https://gmldbd94.tistory.com/148</a></p>
<p><a href="https://blog.leocat.kr/notes/2019/08/22/translation-kubernetes-nodeport-vs-loadbalancer-vs-ingress">https://blog.leocat.kr/notes/2019/08/22/translation-kubernetes-nodeport-vs-loadbalancer-vs-ingress</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[basic] python 함수 정리]]></title>
            <link>https://velog.io/@be-lgreen/basic-python-%ED%95%A8%EC%88%98-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@be-lgreen/basic-python-%ED%95%A8%EC%88%98-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Sun, 06 Jun 2021 02:16:57 GMT</pubDate>
            <description><![CDATA[<h3 id="기본-함수">기본 함수</h3>
<blockquote>
<p>리스트 사이즈: len(a)
정렬: sorted(a)
합: sum(a)
엘리먼트 위치: 리스트.index(찾을 엘리먼트)
엘리먼트 존재 유무: if &#39;a&#39; in b_list:</p>
</blockquote>
<h3 id="list">list</h3>
<h4 id="list-초기화">list 초기화</h4>
<pre><code># 0으로 초기화
a = [0 for _ in range(10)]
print(a)

# 0~9로 초기화
b = [i for i in range(10)]
print(b)

# 10 * 5
c = [[col for col in range(5)] for row in range(10)]
print(c)</code></pre><h3 id="set">set</h3>
<h4 id="중복제거">중복제거</h4>
<pre><code>li = [&quot;12&quot;, &quot;12&quot;, &quot;123&quot;, &quot;1&quot;, &quot;2&quot;, &quot;2&quot;, &quot;3&quot;]
s = list(set(li))
print(s)</code></pre><p><img src="https://images.velog.io/images/be-lgreen/post/9ad2aa17-2900-4718-b767-027ea26ac65d/image.png" alt=""></p>
<h3 id="삽입-삭제">삽입, 삭제</h3>
<pre><code>    # initialize list with 0~9
    b = [i for i in range(10)]
    print(b) #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

    b.append(10)
    print(b) #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

    b.insert(10, 11)
    print(b) #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 10]

    del b[10]
    print(b) #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

    b.pop(10)
    print(b) #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]</code></pre><blockquote>
<p>#추가
마지막 원소 추가 : append(값)
지정된 위치 원소 추가 : insert(인덱스, 값)</p>
</blockquote>
<blockquote>
<p>#삭제
특정 원소 삭제: li.remove(값)
지정된 위치 원소 삭제: del li[인덱스]
지정된 위치 원소 삭제: li.pop(인덱스)
마지막 원소 삭제 : li.pop()</p>
</blockquote>
<h3 id="map">map</h3>
<p>리스트, 딕셔너리와 같이 iterable한 데이터를 인자로 받아
리스트안의 개별 아이템을 함수의 인자로 전달하여 리스트로 반환</p>
<pre><code>def map_grammer():
    li = [i for i in range(5)]
    print(li)

    def func(x):
        return x*2

    result = list(map(func, li))
    print(result)

if __name__ == &quot;__main__&quot;:
    map_grammer()
    # [0, 1, 2, 3, 4]
    # [0, 2, 4, 6, 8]
</code></pre><h3 id="딕셔너리">딕셔너리</h3>
<pre><code>def dict_grammer():
    dict = {
        &quot;a&quot;: 1,
        &quot;b&quot;: 2,
        &quot;c&quot;: 3,
        &quot;d&quot;: 4,
        &quot;e&quot;: 5
    }

    print(dict.get(&quot;f&quot;))
    print(dict.keys())
    print(dict.values())</code></pre><h3 id="정렬sorted-lambda">정렬(sorted, lambda)</h3>
<pre><code>def sort_grammer():
    students = [
        (&#39;hong&#39;, 3.9, 2016303),
        (&#39;kim&#39;, 3.0, 2016302),
        (&#39;choi&#39;, 4.3, 2016301),
    ]
    sorted_list = sorted(students, key=lambda student:student[1], reverse=True)
    print(sorted_list)

if __name__ == &quot;__main__&quot;:
    sort_grammer() # [(&#39;choi&#39;, 4.3, 2016301), (&#39;hong&#39;, 3.9, 2016303), (&#39;kim&#39;, 3.0, 2016302)]
</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[02. 리눅스 명령어 정리]]></title>
            <link>https://velog.io/@be-lgreen/02.-%EB%A6%AC%EB%88%85%EC%8A%A4-%EB%AA%85%EB%A0%B9%EC%96%B4-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@be-lgreen/02.-%EB%A6%AC%EB%88%85%EC%8A%A4-%EB%AA%85%EB%A0%B9%EC%96%B4-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Sun, 30 May 2021 05:25:40 GMT</pubDate>
            <description><![CDATA[<h2 id="ps--ef-vs-ps-aux">ps -ef vs ps aux</h2>
<hr>
<h3 id="명령어-설명">명령어 설명</h3>
<blockquote>
<p>ps -e : 프로세스 목록
ps ax : 프로세스 목록</p>
</blockquote>
<blockquote>
<p>ps -f : 프로세스 식별 정보를 더 잘 보여줌
 ps u : 프로세스 상태 정보를 더 잘 보여줌 </p>
</blockquote>
<h3 id="예시">예시</h3>
<p> <img src="https://images.velog.io/images/be-lgreen/post/438c47cd-559a-4d74-9a83-20ba5879dd6e/image.png" alt=""></p>
<blockquote>
</blockquote>
<p> %CPU : CPU 사용율
 %MEM : 메모리 사용율
 VSZ : 가상 메모리 크기
 RSS : 실제 메모리 크기
 STAT : 프로세스 상태</p>
<h3 id="결론">결론</h3>
<p> 부모 프로세스와 자식 프로세스의 관계를 보려면 ps -ef가
프로세스 상태를 보는 용도로는 ps aux가 더 적당하다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[9. Networking - pre]]></title>
            <link>https://velog.io/@be-lgreen/9.-Networking-pre</link>
            <guid>https://velog.io/@be-lgreen/9.-Networking-pre</guid>
            <pubDate>Mon, 24 May 2021 16:08:54 GMT</pubDate>
            <description><![CDATA[<h1 id="1-switching-routing">1. Switching Routing</h1>
<hr>
<h1 id="2-dns">2. DNS</h1>
<hr>
<p>/etc/name</p>
<p>00파일에 지정한 내용과 내부 DNS에 지정한 내용 중 파일에 지정한 내용이 우선 적용된다.</p>
<p>내부 DNS에서 정의되지 않은 ip주소의 경우, 내부 DNS에는 8.8.8.8 구글 퍼블릭 DNS로 포워딩하도록 설정 되어있다.</p>
<p>내부 DNS -&gt; 루트 DNS -&gt; ...
내부 DNS에서는 다음번에 빠르게 찾기 위해서 캐싱을 해둔다.</p>
<h1 id="3-coredns">3. CoreDNS</h1>
<hr>
<h1 id="4-network-namespace">4. Network Namespace</h1>
<hr>
<h2 id="네트워크-네임스페이스-생성">네트워크 네임스페이스 생성</h2>
<blockquote>
<p>ip netns add &lt;네임스페이스 이름&gt;</p>
</blockquote>
<h2 id="네트워크-네임스페이스-리스트-확인">네트워크 네임스페이스 리스트 확인</h2>
<blockquote>
<p>ip netns </p>
</blockquote>
<h2 id="ip">ip</h2>
<p>네트워크 인터페이스 관리 명령어 중 하나이다. 네트워크 인터페이스 정보를 확인하기 위해 사용할 수 있다.</p>
<blockquote>
<p>ip link</p>
</blockquote>
<p>네트워크 네임스페이스 내 네트워크 인터페이스 정보를 확인하기 위해서는</p>
<blockquote>
<p>ip netns exec &lt;네트워크 네임스페이스 이름&gt; ip link</p>
</blockquote>
<p>네트워크 네임스페이스 안에서 인터페이스 정보를 확인하면 로프백 정보만 보이고 호스트의 네트워크 인터페이스 정보는 보이지 않는다. 이는 호스트의 네트워크 인터페이스가 네임스페이스 안에 노출되지 않도록 한다.</p>
<p>가상이더넷(veth)으로 두 네임스페이스를 연결할 수 있다.</p>
<blockquote>
<p>iP link add veth-red type veth peer name veth-blue : veth 만든다.
ip link set veth-red netns red : 각 veth를 네임스페이스에 붙인다.
ip link set veth-blue netns blue</p>
</blockquote>
<blockquote>
<p>ip &lt;옵션&gt; &lt;오브젝트&gt; &lt;명령 옵션&gt;</p>
</blockquote>
<blockquote>
<p>&lt;옵션&gt;
addr: IP 주소에 관한 정보를 수정하거나 출력
link: 네트워크 인터페이스의 상태를 관리하거나 출력
route: 라우팅 테이블을 변경하거나 출력    </p>
</blockquote>
<blockquote>
<p>&lt;명령 옵션&gt;
add, del, set</p>
</blockquote>
<p>다음으로 ip 주소를 각 네임스페이스에 할당한다.</p>
<blockquote>
<p>ip -n red addr 192.168.x.x dev veth-red</p>
</blockquote>
<p>up 명령어 후에 각 네임스페이스 서로 접근가능한다.</p>
<blockquote>
<p>ip -n red link set veth-red up
ip -n blue link set veth-blue up</p>
</blockquote>
<p>적용완료 되었는지 red 네임스페이스 안에서 blue 네임스페이스에 ping 한다.</p>
<blockquote>
<p>ip netns exec red ping 192.168.x.x</p>
</blockquote>
<h2 id="네트워크-네임스페이스가-많을-경우에는-어떻게-할까">네트워크 네임스페이스가 많을 경우에는 어떻게 할까?</h2>
<p>네트워크 네임스페이스가 많아지면 모든 네트워크 네임스페이스끼리 직접 이어주기 힘들것이다. 따라서 중앙에 가상 스위치를 두고 모든 네임스페이가 이 스위치에 연결하여 서로 통신한다.</p>
<p>가상 스위치 오픈소스로는 linux bridge, Open vSwitch 등이 있다.</p>
<p>linux bridge에 대해 더 자세하게 알아보자.</p>
<h3 id="birdge-스위치-생성--up">birdge 스위치 생성 + up</h3>
<blockquote>
<p>ip link add v-net-0 type bridge
ip link set dev v-net-0 up</p>
</blockquote>
<h3 id=""></h3>
<blockquote>
<p>ip link add veth-red type veth peer name veth-red-br
ip link add veth-blue type beth peer name veth-blue-br</p>
</blockquote>
<p>네임스페이스와 브릿지 네트워크게 가상네트워크를 할당한다 ?</p>
<blockquote>
<p>ip link set veth-red netns red
ip link set veth-red-br master v-net-0</p>
</blockquote>
<p>다음으로 ip 주소를 각 네임스페이스에 할당한다.</p>
<blockquote>
<p>ip -n red addr 192.168.x.x dev veth-red
ip -n blue addr 192.168.x.x dev veth-blue</p>
</blockquote>
<p>up 명령어 후에 각 네임스페이스 서로 접근가능한다.</p>
<blockquote>
<p>ip -n red link set veth-red up
ip -n blue link set veth-blue up</p>
</blockquote>
<h3 id="호스트에서-네임스페이스에-ping">호스트에서 네임스페이스에 ping</h3>
<p>브릿지 네트워크는 호스트의 네트워크 인터페이스이다. 따라서 브릿지 네트워크에 ip를 할당하면, 호스트와 브릿지 네트워크와 연결된 네임스페이스와 통신이 가능하다.</p>
<blockquote>
<p>ip addr add 192.168.15.5/24 dev v-net-0</p>
</blockquote>
<p>이제 호스트에서 ping &lt;네임스페이스에 할당된 ip주소&gt; 명령어를 입력하면 응답이 올 것이다.</p>
<h3 id="네임스페이스에서-외부네트워크에-접근하기">네임스페이스에서 외부네트워크에 접근하기</h3>
<p>호스트 내부 네트워크 네임스페이스에서 외부 LAN으로 접근하기 위해서는 네임스페이스 라우터에 설정을 추가해야한다.</p>
<p>플로우는 다음과 같다. 호스트가 게이트웨이 역할을 한다고 할 수 있다.</p>
<blockquote>
<p>네임스페이스 - 호스트 내 브릿지 네트워크 IP -&gt; 외부 LAN</p>
</blockquote>
<p>하지만 다시 외부에 ping을 보내면 응답을 받지 못한다. 이유는 private ip로 요청을 보냈기 때문에 받는 쪽에서는 어디로 응답을 줘야할지 모르기 때문이다. 따라서 NAT를 설정해주어야 한다.</p>
<blockquote>
<p>iptable -t nat -A POSTROUTING -s 192.168.15.0/24 -j MASQUERADE</p>
</blockquote>
<h3 id="네임스페이스에서-인터넷에-접근하기">네임스페이스에서 인터넷에 접근하기</h3>
<p>네트워크 네임스페이스 인터넷으로 접근하기 위해서는 네임스페이스 라우터에 설정을 추가해야한다.</p>
<p>플로우는 다음과 같다. </p>
<blockquote>
<p>네임스페이스 -&gt; 호스트 내 브릿지 네트워크 ip -&gt; 인터넷</p>
</blockquote>
<blockquote>
<p>ip netns exec blue ip route add default via 192.168.15.5 &lt;네트워크 브릿지 ip 주소&gt;</p>
</blockquote>
<blockquote>
<p>ip netns exec blue ping 8.8.8.8</p>
</blockquote>
<h3 id="외부-네트워크에서-네임스페이스-ip로-접근-가능하게-하기">외부 네트워크에서 네임스페이스 IP로 접근 가능하게 하기</h3>
<p>외부에서 네임스페이스 ip로 ping을 가능하게 하려면 port forwarding을 해주면된다.</p>
<h3 id="기타-명령어">기타 명령어</h3>
<h4 id="ifconfig">ifconfig</h4>
<p>네트워크 인터페이스 관리 명령어 중 하나이다. 네트워크 인터페이스 정보를 확인하기 위해 사용할 수 있다.</p>
<blockquote>
<p>ifconfig &lt;옵션&gt; &lt;인터페이스&gt;</p>
</blockquote>
<blockquote>
<p>&lt;인터페이스&gt; up : 지정한 인터페이스 활성화
&lt;인터페이스&gt; down : 지정한 인터페이스 비활성화
inet &lt;주소&gt; : 지정한 인터페이스 IP 주소 설정
netmask &lt;주소&gt; : 지정한 인터페이스 넷 마스크 설정</p>
</blockquote>
<blockquote>
<p>예) ifconfig
예) ifconfig eth0</p>
</blockquote>
<h4 id="arp">arp</h4>
<p>arp 테이블을 확인하는 명령어이다.</p>
<h4 id="route">route</h4>
<p>route 테이블을 확인하는 명령어이다.</p>
<h1 id="docker-networking">docker networking</h1>
<hr>
<p>2) 네트워크 지정 X
3) 네트워크 브릿지</p>
<blockquote>
<p>docker network ls
<img src="https://images.velog.io/images/be-lgreen/post/462cdc6a-f27a-46a7-8f7b-d5d4d7c3e507/image.png" alt=""></p>
</blockquote>
<blockquote>
<p>ip link 후 docker01 부분 확인
<img src="https://images.velog.io/images/be-lgreen/post/b84e8880-6455-4ee8-a05e-1c99ea5fbc1d/image.png" alt=""></p>
</blockquote>
<blockquote>
<p>ip addr 후 docker01 부분 확인</p>
</blockquote>
<p>도커에서 80번 포트로 애플리케이션을 서비스하고 있다고하자. (nginx)
도커 호스트 머신에서 curl &lt;도커ip&gt;:80을 하면 응답이 오지만, 호스트 외부에서 curl을 보내면 응답이 정상적이지 않다.</p>
<p>외부에서 애플리케이션에 요청을 보내기위해서는 아래와 같이 host mapping을 해주어야한다.</p>
<blockquote>
<p>docker run -p 8080:80 nginx</p>
</blockquote>
<p>해석하자면 호스트머신의 8080포트로 들어오는 트래픽을 컨테이너의 80포트로 보낸다는 의미이다.</p>
<blockquote>
<p>iptables -nvL -t nat</p>
</blockquote>
<h1 id="container-networking-interface-cni">Container Networking Interface (CNI)</h1>
<hr>
<p>컨테이너 환경에서 네트워크 설정 절차를 정의해둔 일종의 플러그인?이다.</p>
<blockquote>
<p>birdge add <cid> <namespace></p>
</blockquote>
<p>docker는 특이하게 CNI를 구현하고 있지 않고 자체 정의한 Container Network Model(CNM)이 구현되어 있다.</p>
<p>  ??
docker에서 CNI를 사용하려면 일일히 컨테이너마다 evoke를 해주어야하는데
k8s는 docker와 CNI를 사용하면서 evoke하는 것을 지원하고 있다.//????</p>
<blockquote>
<p>netstat -plnt</p>
</blockquote>
<p>p: 프로그램 이름 / PID
l(listen) : 연결 가능한 상태
n(number port) : 포트 넘버
t(tcp) : tcp</p>
<blockquote>
<p>netstat -anp | grep etcd</p>
</blockquote>
<blockquote>
<p>netstat -nap : 연결을 기다리는 목록과 프로그램을 보여준다
netstat -an | grep 포트번호 : 특정 포트가 사용 중에 있는지 확인 
netstat -nlpt : TCP listening 상태의 포트와 프로그램을 보여준다</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[2. Core Concepts]]></title>
            <link>https://velog.io/@be-lgreen/2.-Core-Concepts</link>
            <guid>https://velog.io/@be-lgreen/2.-Core-Concepts</guid>
            <pubDate>Sat, 22 May 2021 09:11:22 GMT</pubDate>
            <description><![CDATA[<h1 id="1-cluster-architecture">1. Cluster Architecture</h1>
<p>master node -&gt; worker nodes에 대한 관리 / 계획 / 스케줄 / 노드 모니터링
worker node -&gt; 컨테이너로 애플레케이션 호스트</p>
<p>master node에는 control plane이 존재</p>
<h2 id="master-node-control-plane-컴포넌트">Master Node (Control Plane 컴포넌트)</h2>
<h3 id="etcd-cluster">ETCD Cluster</h3>
<h3 id="kube-scheduler">kube-scheduler</h3>
<p>컨테이너에 필요한 자원 요구량, 워커 노드의 스펙, node afiinity role, taint, toleration 등을 고려하여 컨테이너를 노드에 할당</p>
<h3 id="controller-manager-node-controller-replication-controlelr">Controller Manager (Node-Controller, Replication-Controlelr)</h3>
<p>node-controller -&gt; 노드에 대한 관리, 클러스터에 노드 할당, 노드가 이용불가능한 상태일때 이를 지움
replication-controller -&gt; 지정해둔 replicaset 만큼의 컨테이너를 유지한다.</p>
<h3 id="kube-apiserver">kube-apiserver</h3>
<p>controller 간의 소통
클러스터 안에 잇는 모든 컨포넌트 간의 소통 담당</p>
<p>워커노드에있는 애플리케이션 부터
마스터노드에 있는 control plane 컴포넌트까지 모든 컨테이너로 배포될 수 있다. 따라서 컨테이너 런타임 엔진 (대표적으로 도커)가 워커노드와 마스터노드에 모두 있다.</p>
<h2 id="worker-node">Worker Node</h2>
<h3 id="kubelet">kubelet</h3>
<p>노드에 존재하는 에이전트로 노드안에 컨테이너를 생성하고 지우기도 하고, 노드의 상태를 통신하는 역할도 한다
노드간의 통신도 담당 (?)
모든 노드에는 kubelet에 존재하여 노드와 컨테이너 상태를 kube-apiserver를 통해 통신한다.</p>
<h3 id="kube-proxy">kube-proxy</h3>
<p>클러스터 안에있는 서비스간의 통신을 담당.</p>
<h1 id="2-etcd">2. ETCD</h1>
<h1 id="3-kube-apiserver">3. Kube-apiserver</h1>
<p>kube-apiserver 옵션확인</p>
<p>kubeadm) cat /etc/kubernetes/manifests/kube-apiserver.yaml</p>
<p>??) cat /etc/systemd/system/kube-apiserver.service</p>
<p>ps -aux | grep kube-apiserver</p>
<h1 id="4-kube-controller-manager">4. kube-Controller Manager</h1>
<p>--node-monitor-period=5s
--node-monitor-grace-period=40s
--pod-eviction-timeput=5m0s</p>
<p>kubectl get pods -n kube-system</p>
<p>kubeadm) cat /etc/kubernetes/manifests/kube-controller-manager.yaml</p>
<p>non-kubeadm) cat /etc/systemd/system/kube-controller-manager.service</p>
<p>ps -aux | grep kube-controller-manager</p>
<h1 id="5-kube-scheduler">5. Kube Scheduler</h1>
<p>kube-scheduler는 어떤 pod가 어떤 node르 스케줄링 될지만 정하고, 실제 할당은 각 node에 있는 kubelet이 수행한다.</p>
<p>*pod를 node에 할당하는 프로세스</p>
<p>1) 요구 자원 스펙에 못미치는 node를 피터링한다.
2) rank nodes
pod를 할당하고 남은 양이 많은 순으로...(?) 커스터마이즈 가능 (?)
3) 이외에
Resource Requirements and Limits
Taints and Tolerations
Node Selectors/Affinity
를 고려하여 스케줄링 한다.</p>
<p>kubeadm 툴을 이용하여 kube Schduler을 설치한 경우, 
kubeadm은 마스터노드의 kube-system 네임스페이스에 Pod로 배포한다.</p>
<ul>
<li>kube-scheduler 옵션 확인 방법</li>
</ul>
<p>kubeadm) cat /etc/kubernetes/manitests/kube-scheduler.yaml</p>
<p>ps -aux | grep kube-scheduler</p>
<h1 id="6-kubelet">6. kubelet</h1>
<p>1) kubelet -&gt; kube-apiserver -&gt; kube-sceduler</p>
<p>kube-apiserver를 통해 노드를 레지스터 한다.</p>
<p>2) kube-scheduler의 결정에 따라 노드에 파드를 생성한다.</p>
<p>3) 노드와 파드를 모니터링하고 일정시간 간격으로 kube-apiserver에 전달한다.</p>
<p>다른 컴포넌트와 다르게 kubeadm은 kubelet을 배포하지 않는다. 워커 노드에 항상 수동으로 배포해야한다.</p>
<p>kubelet의 옵션을 확인하려면 워커 노드에서 
ps -aux | grep kubelet으로 확인한다.</p>
<h1 id="7-kube-proxy">7. kube-proxy</h1>
<p>클러스터 안의 파드는 모두 통신가능</p>
<p>파드의 아이피는 항상 바뀜</p>
<p>데이터베이스 애플리케이션을 클러스터에 노출시키기 위해 service사용</p>
<p>service도 아이피를 가지고 있음</p>
<p>서비스는 컨테이너가 아니다, virtual component in k8s memory</p>
<p>하지만 서비스에서 각노드로 통신이 가능하다 이것이 가능한 이유는 kube-proxy가 존재하기 때문...하 모르겠당ㅇㅅㅇ</p>
<p>kube-proxy는 각 노드에 있는 일종의 프로세스이다.
kube-proxy는 새로운 서비스가 생성되는지 항상 감시하고, 서비스가 새로감지되면 서비스로 백에드 파드로 트래픽을 포워딩할 룰(iptable rules)을 생성한다.</p>
<p>kubectl get pods -n kube-system
kubectl get daemonset -n kube-system
(kube-proxy는 daemonset으로 각가의 노드에 생성된다.)</p>
<h1 id="8-pod">8. POD</h1>
<ul>
<li><p>컨테이너는 노드에 바로 배포되지 않고 pod라는 오브젝트안에 넣어서 배포된다.</p>
</li>
<li><p>pod는 쿠버네티스에서 생성할 수 있는 가장 작은 컴포넌트다.</p>
</li>
<li><p>Scale out, Scale in시, 컨테이너가 생성되는 것이아니라 pod가 생성된다.</p>
</li>
<li><p>애플리케이션 컨테이너와, helper 컨테이너를 하나의 pod가 배포할 수 있다. 같은 네트워크와 스토리지를 사용한다.</p>
</li>
<li><p>pod 개념이 없다면 새로운 컨테이너를 만들때마다 helper컨테이너도 같이만들어주고 둘 사이의 네트워크르르 이어주어야 한다. 하지만 pod 개념이 존재하므로 이를 한꺼번에 처리가능하다.</p>
</li>
</ul>
<h3 id="명령어">명령어</h3>
<blockquote>
<p>kubectl run nginx --image nginx
(해당 이미지를 사용하여 파드 생성)</p>
</blockquote>
<blockquote>
<p>kubectl get pods
(파드 리스트 확인)</p>
</blockquote>
<p>외부 사용자가 pod의 nginx에 접근하려고 하면 따로 네트워크를 설정해주어야 함.</p>
<h3 id="yaml">YAML</h3>
<p>yaml파일을 통해 pod만들기</p>
<p>yaml파일에서 
-apiVersion (string)
-kind (string)
-metadata (dictionary) : object게 관한 정보
-spec (dictionary)
은 필수 항목이다.</p>
<p>kind에는
POD/v1
Service/v1
ReplicaSet/ apps/v1
Deployment/ apps/v1
등이 가능하다.</p>
<blockquote>
</blockquote>
<p>! pod-difinition.yml
metadata:
    name: myapp-pod
    labels: 
        app: myapp
        env: test 
spec:
    containers:
        - name: nginx-controller
          image: nginx
        - name: backend-container
          image: redis</p>
<p>containers는 list/array이다. -로 시작하는건 배열의 첫번째 항목이라 할 수 있다.
containers라는 배열안에 각각의 컨테이너가 dictionary형태로 정의되어있다.</p>
<blockquote>
<p>kubectl create -f pod-definitions.yml</p>
</blockquote>
<blockquote>
<p>kubectl get pods</p>
</blockquote>
<blockquote>
<p>kubectl describe pod myapp-pod</p>
</blockquote>
<h1 id="9-replication-controllerreplicasets">9. Replication Controller(ReplicaSets)</h1>
<h2 id="replication-controller의-역할">Replication Controller의 역할</h2>
<p>1) 최소 지정한 n개의 pod가 노드에 떠있도록 유지하여, 사용자가 서비스에 엑세스할 수 없는 일을 방지한다.</p>
<p>2) Load Balncing &amp; Scaling 
트래픽이 많아지면 pod를 수를 증가시켜 트래픽을 분산한다. </p>
<p>한쪽 워커 노드에 자원을 다 사용하면 클러스터내에 있는 다른 워커 노드에 pod를 생성한다. replication controller가 다수 node에 걸쳐있다고 생각할 수 있다. </p>
<h2 id="replication-controlelr-vs-replica-set">Replication Controlelr VS Replica Set</h2>
<p>replication controlelr가 더 오래된 개념이고, Replica set이 더 최근에 등장한 개념으로 Replica Set을 사용하는 것이 권고되고 있다.</p>
<p>replication controller와 다르게 ReplicaSet 정의 시, version은 app/v1을 사용하고 selector 정의 항목이 존재한다.</p>
<h2 id="replication-controller-yaml-생성">Replication Controller yaml 생성</h2>
<p><img src="https://images.velog.io/images/be-lgreen/post/ec8cd694-8dad-4381-a93a-4189629040ca/image.png" alt=""></p>
<blockquote>
<p>kubectl create -f replication-contoller.yml 
kubectl get replicationController
kubectl get pods</p>
</blockquote>
<h2 id="replicaset-yaml-생성">ReplicaSet yaml 생성</h2>
<p><img src="https://images.velog.io/images/be-lgreen/post/46802fbd-2cc4-435f-9258-e43235dc8911/image.png" alt=""></p>
<blockquote>
<p>kubectl create -f replicaset-definition.yml
kubectl get replicaset
kubectl get pods</p>
</blockquote>
<h2 id="scale">Scale</h2>
<blockquote>
<p> replicaset-definition.yml 파일에서 replcias 수 수정
Kubectl replace -f replicaset-definition.yml</p>
</blockquote>
<blockquote>
<p>kubectl scale --replicas=6 -f replicaset-definition.yml
( 파일 명을 지정하더라도 파일 내용 중 replicat수가 저절로 수정되지 않는다.)</p>
</blockquote>
<blockquote>
<p>kubectl dscale --replicas=6 replicaset myapp-replicaset
( type / name )</p>
</blockquote>
<h2 id="replicaset-관련-명령어">replicaset 관련 명령어</h2>
<blockquote>
<p>kubectl delete replicaset myapp-relicaset
( 해당 하는 pod도 모두 지운다.)</p>
</blockquote>
<h1 id="10-deployments">10. Deployments</h1>
<p>컨테이너 &lt; 파드 &lt; Replica Set &lt; Deployment 순으로 하위 개념을 포함하는 형태라고 할 수 있다.</p>
<h2 id="명령어-1">명령어</h2>
<blockquote>
<p>kubectl create -f deployment-definition.yml</p>
</blockquote>
<blockquote>
<p>kubectl get deployments</p>
</blockquote>
<blockquote>
<p>kubectl get replicaset</p>
</blockquote>
<blockquote>
<p>kubectl get pods</p>
</blockquote>
<blockquote>
<p>kubectl get all</p>
</blockquote>
<h1 id="11-namespaces">11. Namespaces</h1>
<p>쿠버네티스에 의해 자동으로 만들어지는 namespaces는 
Default, kube-system, kube-public이 있다.</p>
<p>1) Default
2) kube-system
유저가 실수로 삭제하는 것을 방지하기 위해, Kube-system 이라는 namespaces에 DNS, 네트워크 관련 오브젝트들이 존재한다.
3) kube-public
모든 유저가 접근할 수 있는 자원들</p>
<p>각 네임스페이스는 누가 무엇을 할수 있는지에 대한 pilicy를 가지고 있고 resource limit이 존재한다. </p>
<p>다른 네임스페이스 있는 오브젝트에 접근할 때는 다음과 같은 이름규칙을 사용한다.</p>
<p>db-service.dev.svc.cluster.local
(service name / namespace / service / domain)</p>
<h2 id="kubectl-명령어와-네임스페이스-지정">kubectl 명령어와 네임스페이스 지정</h2>
<blockquote>
<p>kubectl get pods (default 네임스페이스에 존재하는 파드 리스트 조회)</p>
</blockquote>
<blockquote>
<p>kubectl get pods --namespac=kube-system
(kube-system 네임스페이스에 존재하는 파드 리스트 조회)</p>
</blockquote>
<blockquote>
<p>kubectl create -f pod-definition.yml</p>
</blockquote>
<blockquote>
<p>kubectl create -f pod-definition.yml --namespace=dev
(dev 네임스페이스에 파드 생성 / 항상 Dev 네임스페이스에 파드를 배포하기 위해서는 pod 정의 yml 파일 내 metadata 영역에 네임스페이스를 지정할 수 있다.)</p>
</blockquote>
<p><img src="https://images.velog.io/images/be-lgreen/post/64347745-6158-4525-8c15-596e74889dea/image.png" alt=""></p>
<h2 id="네임스페이스-생성">네임스페이스 생성</h2>
<p>1) yml 파일 
<img src="https://images.velog.io/images/be-lgreen/post/0cb99c8f-1ef4-44aa-b2d1-69141f997b66/image.png" alt=""></p>
<blockquote>
<p>kubectl create -f namespace-dev.yml</p>
</blockquote>
<p>2) 명령어 </p>
<blockquote>
<p>kubectl create namespace dev</p>
</blockquote>
<h2 id="네임스페이스-이동">네임스페이스 이동</h2>
<blockquote>
<p>kubectl config set-context $(kubectl config current-context) --namespace=dev</p>
</blockquote>
<p>(kubectl config current-context)
현재 컨텍스트 가져옴</p>
<blockquote>
<p>kubectl get pods (dev 네임스페이스의 파드 리스트 가져옴) </p>
</blockquote>
<blockquote>
<p>kubectl get pods --all-namespaces (모든 네임스페이스의 파드 리스트 가져옴)</p>
</blockquote>
<h2 id="네임스페이스-quota">네임스페이스 Quota</h2>
<p><img src="https://images.velog.io/images/be-lgreen/post/294d3676-1d2d-4652-b809-ea59b7c1fe45/image.png" alt=""></p>
<blockquote>
<p>kubectl create -f compute-quota.yml</p>
</blockquote>
<h1 id="12-services">12. Services</h1>
<p>파드 그룹간 네트워크 통신이 가능하도록 한다.</p>
<p>MSA환경에서 커플링을 없애는 역할을 한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[7. Security]]></title>
            <link>https://velog.io/@be-lgreen/7.-Security</link>
            <guid>https://velog.io/@be-lgreen/7.-Security</guid>
            <pubDate>Mon, 17 May 2021 11:53:58 GMT</pubDate>
            <description><![CDATA[<p>유데비 CKA강의를 들으면서 정리한 문서입니다. 따로 정리한 글이 아니라 강의 중간에 메모한 문서이기 때문에 틀린부분이 존재할수도 있습니다.</p>
<h1 id="1-kubernetes-security-primitives">1. Kubernetes Security Primitives</h1>
<h1 id="2-authentication">2. Authentication</h1>
<h1 id="3-tls-certificates-for-cluster-components">3. TLS Certificates for Cluster Components</h1>
<p>Server Certificates for Servers</p>
<p>1) kube-apiserver 
2) etcd server
3) kubelet server
워커노드에 있는 kubelet은 https 엔드포인트가 존재하기 때문에</p>
<p>Client Certificates for Clients</p>
<p>1) kube-apiserver에 접속하는 클라이언트는 
admin, kube-scheduler(새로 생성된 파드를 인지하거나, 파드를 워커노드에 할당하기 위해), kube-controller-manager, kube-proxy</p>
<p>2) etcd server에 통신하는 유일한 클라이언트는 kube-apiserver</p>
<p>서버용 인증은 클라이언트 인증으로 사용할수도 있고, 클라이언트용 인증을 새로 생성할수도 있다.</p>
<p>3) kubelet에 통신하는 클라이언트는 kube-apiserver</p>
<h2 id="인증서-생성">인증서 생성</h2>
<p>1) easyrsa
2) openssl</p>
<blockquote>
<p>openssl genrsa -out ca.key 2048
(키 생성)</p>
</blockquote>
<blockquote>
<p>openssl req -new -key ca.key -subj &quot;/CN=KUBERNETES-CA&quot; -out ca.csr
(Certificate Signing Request)</p>
</blockquote>
<blockquote>
<p>openssl x509 -req -in ca.csr -signkey ca.key -out ca.crt
(Sign Certificates)</p>
</blockquote>
<p>3) cfssl</p>
<h1 id="4-secure-persistent-key-value-store">4. Secure Persistent Key Value Store</h1>
<h1 id="5-authorization">5. Authorization</h1>
<h1 id="6-images-securely">6. Images Securely</h1>
<h1 id="7-security-contexts">7. Security Contexts</h1>
<h1 id="8-network-policies">8. Network Policies</h1>
]]></description>
        </item>
        <item>
            <title><![CDATA[리눅스 퍼포먼스 분석]]></title>
            <link>https://velog.io/@be-lgreen/%EB%A6%AC%EB%88%85%EC%8A%A4-%ED%8D%BC%ED%8F%AC%EB%A8%BC%EC%8A%A4-%EB%B6%84%EC%84%9D</link>
            <guid>https://velog.io/@be-lgreen/%EB%A6%AC%EB%88%85%EC%8A%A4-%ED%8D%BC%ED%8F%AC%EB%A8%BC%EC%8A%A4-%EB%B6%84%EC%84%9D</guid>
            <pubDate>Mon, 17 May 2021 04:55:45 GMT</pubDate>
            <description><![CDATA[<p>(작성중)
<a href="https://netflixtechblog.com/linux-performance-analysis-in-60-000-milliseconds-accc10403c55">Linux Performance Analysis in 60,000 Milliseconds</a> 문서를 읽고 정리한 글입니다.</p>
<p>참고
<a href="https://performance.tistory.com/27">Throughput (쓰루풋) 오해와 진실</a></p>
<h1 id="서론">서론.</h1>
<p>요즘 여러 모니터링 툴이 존재하지만, 이 문서에서는 별도의 모니터링 툴을 사용하지 않고 직접 리눅스 서버에 접속하여 10가지 리눅스 명령어를 통해 성능을 확인하는 방법에 대해 알아본다.</p>
<h1 id="본론">본론.</h1>
<h2 id="1-uptime">1. uptime</h2>
<p><img src="https://images.velog.io/images/be-lgreen/post/7742eaa5-2813-4fb9-9324-cc573e6c69bf/image.png" alt=""></p>
<p>서버의 로드 평균을 알아볼 수 있다. 즉 실행을 기다리는 프로세스의 개수이다.
왼쪽부터 1분간 평균, 5분간 평균, 15분간 평균을 나타낸다.</p>
<h2 id="2-dmesg--tail">2. dmesg | tail</h2>
<p><img src="https://images.velog.io/images/be-lgreen/post/53eb907c-5a58-4fd9-9fa7-6889c2a54231/image.png" alt=""></p>
<p>최근 10개 시스템 메시지를 보여준다.</p>
<h2 id="vmstat-1">vmstat 1</h2>
<p><img src="https://images.velog.io/images/be-lgreen/post/88f2e60d-55c9-4888-a58f-e7b5286160a9/image.png" alt=""></p>
<p>r -&gt; Number of processes running on CPU and waiting for a turn. CPU 포화 정도를 알 수 있음. r이 cpu 개수 보다 많은 정도가 포화 정도이다. </p>
<p>free -&gt; free memory(kilobytes) / free -m 명령어을 사용하면 더 상세하게 볼 수 있음.</p>
<p>si,so -&gt; Swap-ins, swap-outs / 0아니면 메모리가 부족한 것임.</p>
<p>us(user time), sy(system time), id(idle) ,wa(wait I/O) ,st(stolen time) -&gt; cpu time의 상세.</p>
<h1 id="그냥-궁금해서-찾아본-것">그냥 궁금해서 찾아본 것.</h1>
<p>Disk Read I/O Byte와 Iops 관계</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[01. kubernetes 명령어 정리]]></title>
            <link>https://velog.io/@be-lgreen/0.-%EB%AA%85%EB%A0%B9%EC%96%B4-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@be-lgreen/0.-%EB%AA%85%EB%A0%B9%EC%96%B4-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Sat, 15 May 2021 07:59:21 GMT</pubDate>
            <description><![CDATA[<p>kubectl get pods -o wide</p>
<p>namespace 지정
--all-namespaces
--namespace kube-system
-n kube-system</p>
<p>kubectl describe pod etcd-controlplan -n kube-system</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[6. Cluster Maintenance]]></title>
            <link>https://velog.io/@be-lgreen/6.-Cluster-Maintenance</link>
            <guid>https://velog.io/@be-lgreen/6.-Cluster-Maintenance</guid>
            <pubDate>Sat, 15 May 2021 07:53:13 GMT</pubDate>
            <description><![CDATA[<p>유데비 CKA강의를 들으면서 정리한 문서입니다. 따로 정리한 글이 아니라 강의 중간에 메모한 문서이기 때문에 틀린부분이 존재할수도 있습니다.</p>
<h1 id="1-drain-cordon-uncordon-os-upgrade">1. drain, cordon, uncordon (os upgrade)</h1>
<h2 id="개념">개념</h2>
<p>노드가 다운되었다가 5분안에 다시 online상태가 되면, 노드안의 파드는 그대로 있다. 하지만 노드가 5분이상 다운되면 쿠버네티스는 노드가 종료되었다고 판단하여 노드안의 파드를 종료시켜 버린다. 5분후에 다시 노드를 online상태로 만들더라도 파드를 다시 생성해줘야 한다.</p>
<p>5분이라는 시간은 디폴드 설정값이며 --pod-eviction-timeout을 통해 이 설정을 변경할 수 있다.</p>
<pre><code>kube-controller-manager --pod-eviction-timeout=5m0x</code></pre><p>한 워커 노드가 5분이상 다운되었다고 가정해보자. 노드에 포함된 파드가 replica set인 경우에는 노드가 다운되는 순간 다른 워커 노드에 해당 파드가 생성될 것 이다. 하지만 replica set이 아닌 파드는 다운되었을때, 복구되었을때 생성되지 않을것이다.</p>
<p>os upgrade를 위한 절차는 다음과 같다.</p>
<pre><code>kubectl drain node-1 ( node-1 워커노드에 pod가 생성되지 않도록 제한을 건다.)
node-1 reboot
kubectl cordon node-2 (drain과 다르게 노드가 내려가고 노드 안에 잇는 pod가 다른 살아있는 노드로 옮겨가는것이 아니다. 단순히 pod가 스케줄되지 않도록 설정하는 것)
kubectl uncordon node-1 ( uncordon 한다고 다른 node에 있는 pod가 저절로 node-1에 오지 않는다. / 새로 파드를 생성하면 node-1에 스케줄링 될 수도 있다. / 또는 다른 노드에서 파드를 삭제하면 node-1로 스케줄리 될 수도 있다.</code></pre><h2 id="관련-명령어">관련 명령어</h2>
<h3 id="drain-명령어">drain 명령어</h3>
<pre><code>kubectl drain node01 --ignore-daemonsets
(daemonsets으로 만들어진 파드를 제외하고 drain)</code></pre><p><a href="https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#drain">--ignore-daemonsets 옵션 설명 참고</a></p>
<p><em>ReplicatinoController, ReplicaSet, Job, Daemonsets, StatefulSet으로 관리되지 않는 파드가 node01에 존재하는 경우 drain 명령어에서 오류가 난다.
<img src="https://images.velog.io/images/be-lgreen/post/b52b6fd1-a5f9-4c56-9608-dc3db88b5789/image.png" alt=""></em></p>
<pre><code>kubectl drain node-1 --ignore-daemonsets --force </code></pre><p>명령어를 통해 강제로 drain할 수 있으나, 관리되지 않는 파드는 영원히 유실될 수 있다.</p>
<h3 id="cordon-명령어">cordon 명령어</h3>
<pre><code>kubectl cordon node-1</code></pre><p>노드에 존재하는 파드는 유지하면서 스케줄링만 안되게하고 싶으면 cordon명령어를 사용하면 된다.</p>
<h3 id="기타-명령어">기타 명령어</h3>
<pre><code>kubectl get nodes</code></pre><p>노드 확인
<img src="https://images.velog.io/images/be-lgreen/post/6a82312d-16f6-4f6e-8fee-4d81c9217f82/image.png" alt="">
status 항목을 통해 SchedulingDisabled인지 확인 가능</p>
<pre><code>kubectl get pods -o wide</code></pre><p>어느 노드에 어느 파드가 존재하는지 확인</p>
<pre><code>kubectl get deployments.apps
kubectl get deplotments 랑 위 명령어가 다른점은 ?????</code></pre><p>어떤 애플리케이션이 노드에 호스팅되고 있는지 확인
A애플리케이션이 여러 파드에 존재할 수도 있음. (?)</p>
<pre><code>kubectl describe node master | grep -i taint</code></pre><p>기본적으로 마스터노드로는 파드가 스케줄되지 않도록 taint되어있다.</p>
<h1 id="2-쿠버네티스-소프트웨어-버전">2. 쿠버네티스 소프트웨어 버전</h1>
<p>v1.18.0
(major, minor, patch)</p>
<p>쿠버네티스의 첫 major 버전인 v1.0은 2015년 6월에 출시
minor버전의 경우 매월 출시
patch의 경우 버그픽스</p>
<p>보통 알파 -&gt; 베타 버전을 거쳐 정식 버전이 된다.</p>
<p>모든 버전 이력은 쿠버네티스 깃헙에서 확인할 수 있다.</p>
<p>controlplane의 컴포넌트인 kube-apiserver, controller-manager, kube-scheduler, kubelet, kube-proxy, kubectl 은 같은 버전을 따라가고 ETCD Cluster, Core DNS은 분리된 프로젝트이기 때문에 각자의 버전이 있다.</p>
<p>[쿠버네티스 컴포넌트] (<a href="https://kubernetes.io/ko/docs/concepts/overview/components/">https://kubernetes.io/ko/docs/concepts/overview/components/</a>)</p>
<p><a href="https://github.com/kubernetes/kubernetes/tree/master/CHANGELOG">쿠버네티스 깃헙</a></p>
<h1 id="3-클러스터-업그레이드">3. 클러스터 업그레이드</h1>
<p>쿠버네티스를 이용하는 환경에 따라 업그레이드 하는 방법은 다른다.
GCP에서 매니지드서비스를 사용하는 경우, Kubeadm을 사용하는 경우, 스크레치(아무기반없이 처음부터 쿠버네티스 구축)인 경우에따라 다르다.</p>
<p>클러스터 업그레이드는 마스터 노드 업그레이드, 워커 노드 업그레이드 2단계를 거친다.</p>
<ol>
<li><p>마스터 노드 업그레이드
마스터 노드를 업그레이드 하는 중에는 마스터 노드에 있는 컴포넌트들이 동작하지 않는다. 예를들어 워커 노드의 파드가 삭제되더라도 재생성하지 않을 것이다. 하지만 워커 노드에 이상이 없는한 사용자들은 서비스를 정상적으로 이용할 수 있다.</p>
</li>
<li><p>워커 노드 업그레이드
워커 노드를 업그레이드하는 방법은 3가지 있다.</p>
</li>
</ol>
<p>첫 번째는, 모든 워커 노드를 한번에 업그레이드 하는것이다. 당연히 업그레이드를 수행하는 동안 사용자들은 서비스를 이용할 수 없다.</p>
<p>두 번째는, 워커 노드를 순차적으로 업그레이드 하는 것이다. 하나씩 업그레이드 되기 때문에 업그레이드 되는 노드안의 파드들은 다른 노드들로 옮겨갈 것이다.</p>
<p>세 번재는, 업그레이드된 버전을 새로운 노드를 추가하고 워크로드를 새로운 노드로 옮기는 것이다.</p>
<p>kubeadm 쿠버네티스 업그레이드</p>
<pre><code>kubeadm upgrade plan</code></pre><p>주의할 점은 kubeadm upgrade는 kublet 업그레이드를 포함하지 않는다. kubeadm 자체도 쿠버네티스와 동일한 버전을 따라간다. </p>
<pre><code>&lt;마스터 노드&gt;
kubectl drain master --ignore-daemonsets

apt-get upgrade -y kubeadm=1.12.0-00
(apt install kubeadm=버전)

kubeadm upgrade apply 1.12.0
(이미지를 pull하고 컴포넌트들을 업그레이드 한다.)
kubectl get nodes
(해당 명령어를 통해 보이는 버전은 apiserver버전이 아니라 각 노드의 kubelet의 버전이다)
kubectl version --short

apt-get upgrade -y kubelet=1.12.0-00
(apt install kubelet=버전)

systemctl restart kubelet
kubectl get nodes

kubectl uncordon master

&lt;워커 노드&gt;
kubectl drain node01

ssh node01

apt-get upgrade -y kubeadm=1.12.0-00
(apt install kubeadm=버전)
apt-get upgrade -y kubelet=1.12.0-00
(apt install kubelet=버전)
kubeadm upgrade node config --kubelet-version v1.12.0
systemctl restart kubelet

logout
(master노드로 돌아옴)

kubectl uncordon node01

node02
node03
node04 
반복</code></pre><p>전체적으로 </p>
<p>1) kubeadm 버전 업그레이드
2) kubeadm을 통해 cluster 컴포넌트 버전 업그레이드
3) kubelet 버전 업그레이드</p>
<p><a href="https://kubernetes.io/ko/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade/">kubeadm으로 배포된 클러스터 업그레이드</a></p>
<h1 id="3-백업--복구">3. 백업 &amp; 복구</h1>
<p>백업 대상
Resource Configuration, ETCD Cluster, Persistent Volumes</p>
<h2 id="resource-configuration-백업">Resource Configuration 백업</h2>
<p>1) 각 리소스들을 설정파일로 정의 후에 생성한다면, github와 같은 버전관리 툴에서 설정파일들을 관리하고 보존할 수 있다.
2) 하지만, 어떤 팀원이 설정파일 변경없이 명령어를 통해 바로 리소스들을 변경한다면, 설정파일은 최신버전으로 유지되지 않을 것이다. 따라서 kube-apiserver에 바로 쿼리하여 설정파일 백업을 만드는 방법이 있다.</p>
<pre><code>kubectl get all -all--namespaces -o yaml &gt; all-deploy-services.yaml</code></pre><h2 id="etcd-cluster-백업">ETCD Cluster 백업</h2>
<p>1) etcd는 클러스터에 존재하는 모든 리소스들의 상태를 저장하고 있다. 마스터 노드에 호스팅되며, etcd 설정 시, --data-dir=/var/lib/etcd 처럼 데이터가 저장될 디렉토리 경로를 지정한다.</p>
<p>2) etcd control utility를 통해 etcd 스냅샷을 생성할 수도 있다.
ETCDCTL_API=3
etcdctl snapshot save sanpshot.db</p>
<pre><code>snapshot save [백업 파일 이름]\
snapshot status [백업 파일 이름]</code></pre><h2 id="etcd-cluster-복구">ETCD Cluster 복구</h2>
<p>1) kube-apiserver을 멈춘다.
kube-apiserver는 ETCD와 연관되어 있기 때문에 멈추고 ETCD를 복구해야한다.</p>
<pre><code>service kube-apiserver stop
etcdctl restore [백업 파일 이름] --data-dir /var/lib/etcd-from-backup
--data-dir=/var/lib/etcd-from-backup(etcd 설정 파일 변경)
systemctl daemon-reload (service daemon 리로드)
service etcd restart (etcd 서비스 재시작)
service kube-apiserver start</code></pre><p>두 방법 모두 장단점이 존재한다. 다만, 매니지드 서비스를 사용할 경우 etcd에 접근권한이 없을 수도 있기 때문에 kube-apiserver에 쿼리하는 방법을 선택하는 것이 좋다.</p>
<pre><code>kubectl get deployments.app,svc,pod
</code></pre><p>todo. 멀티 클러스터 구성
todo. etcd</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[인텔리제이 단축키]]></title>
            <link>https://velog.io/@be-lgreen/%EC%9D%B8%ED%85%94%EB%A6%AC%EC%A0%9C%EC%9D%B4-%EB%8B%A8%EC%B6%95%ED%82%A4</link>
            <guid>https://velog.io/@be-lgreen/%EC%9D%B8%ED%85%94%EB%A6%AC%EC%A0%9C%EC%9D%B4-%EB%8B%A8%EC%B6%95%ED%82%A4</guid>
            <pubDate>Sun, 28 Mar 2021 06:54:12 GMT</pubDate>
            <description><![CDATA[<ol>
<li><p>에디터 창 -&gt; 프로젝트 창
command + 1 (alt + 1)</p>
</li>
<li><p>프로젝트 창 -&gt; 에디터 창
ESC</p>
</li>
<li><p>에디터 창에서 파일 미리 보기
미리보기 열기: space
미리보기 닫기: ESC</p>
</li>
<li><p>에디터 창 최대화
control + shift + F12</p>
</li>
<li><p>열러진 에디터 창 이동
control + tab</p>
</li>
<li><p>에디터 창에서 새로운 파일 생성</p>
</li>
<li><p>프로젝트 창에서 새로운 파일 생성</p>
</li>
</ol>
<p>spring boot controller에서 객체를 return 하면 object mapper에 의해 자동을 json으로 변환후 return 된다.</p>
<p>Object mapper는</p>
<p>object -&gt; json(text) 
로 변환시키는 역할을 한다. Object의 get 메소드를 참조하기 때문에 객체 생성 시, get 메소드를 작성해주지 않으면 에러난다.</p>
<ul>
<li>주의 : 따라서 object mapper가 사용하는 클래스에서 get~~ 어쩌고 로 임의의 메소드를 생성하면, 오류가 발생한다. (serialize, deserizlize할때 발생..?)</li>
</ul>
<p>json(text) -&gt; object
는 default생성자를 필요로 한다.</p>
<p>DTO Entitiy에 JsonInclud 설정하면 null인 필드를 제외하고 json을 내려줄 수 있음.
@JsonInclud(JsonInclud.Include.NOT_NULL)</p>
<p>---------------jpa--------------
Entitiy 생성시, ToString을 Override해야하는 이유.</p>
<p>java의 모든 객체는 Object 클래스를 상속
Object 클래스 안에 ToString() 메소드가 존재</p>
<p>자바에서는 ToString()메소드를 오버라이드 할 것을 권고하고 있음.</p>
<hr>
<h2 id="jpa-프로그래밍">JPA 프로그래밍</h2>
<h3 id="lombok알아보기">Lombok알아보기</h3>
<blockquote>
<p>JPA를 활용할 때, 많이 사용되는 Lombok의 활용법</p>
</blockquote>
<p>@AllArgsConstructor
@NoArgsConstructor
@RequiredConstructor
@Getter
@Setter
@ToString
@Data (@Getter, @Stter, @ToString, @RequiredConstructor 등등을 합친 어노테이션)
@Builder</p>
<p>@EqualsAndHashCode
JPA사용과는 상관없지만, @EqualsAndHashCode또한 오버라이딩 할것을 권고하고 있음. 객체의 동등성 비교를 위해</p>
<h2 id=""></h2>
<h2 id="spring-boot-에러-핸들링">spring boot 에러 핸들링</h2>
<p><a href="https://supawer0728.github.io/2019/04/04/spring-error-handling/">https://supawer0728.github.io/2019/04/04/spring-error-handling/</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[vue 조건부 렌더링]]></title>
            <link>https://velog.io/@be-lgreen/vue-%EC%A1%B0%EA%B1%B4%EB%B6%80-%EB%A0%8C%EB%8D%94%EB%A7%81</link>
            <guid>https://velog.io/@be-lgreen/vue-%EC%A1%B0%EA%B1%B4%EB%B6%80-%EB%A0%8C%EB%8D%94%EB%A7%81</guid>
            <pubDate>Fri, 26 Mar 2021 04:28:40 GMT</pubDate>
            <description><![CDATA[<p>조건에 따라 아예 코드를 지우고 싶다면 v-if 디렉티브를, 코드는 있지만 스타일로 display: none 처리를 하고 싶다면 v-show를 사용해야한다.</p>
<p>browserslist: caniuse-lite is outdated. Please run:
npx braowserslist@latest --update-db</p>
<p>테이블 갱신 시, 리 렌더링
<a href="https://velog.io/@byungjur_96/vue.js-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8%EC%97%98%EB%A6%AC%EB%A8%BC%ED%8A%B8-re-rendering-%ED%95%98%EB%8A%94-%EB%B2%95">https://velog.io/@byungjur_96/vue.js-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8%EC%97%98%EB%A6%AC%EB%A8%BC%ED%8A%B8-re-rendering-%ED%95%98%EB%8A%94-%EB%B2%95</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[PostgreSQL - 기본 쿼리 정리]]></title>
            <link>https://velog.io/@be-lgreen/PostgreSQL-%EA%B8%B0%EB%B3%B8-%EC%BF%BC%EB%A6%AC-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@be-lgreen/PostgreSQL-%EA%B8%B0%EB%B3%B8-%EC%BF%BC%EB%A6%AC-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Thu, 18 Feb 2021 13:48:48 GMT</pubDate>
            <description><![CDATA[<p>select * from pg_database; (전체 데이터베이스 조회)
select * from pg_database where datistemplate = FALSE; (사용자가 생성한 데이터베이스만 조회) </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[ansible - collection 이란]]></title>
            <link>https://velog.io/@be-lgreen/ansible-collection-%EC%9D%B4%EB%9E%80</link>
            <guid>https://velog.io/@be-lgreen/ansible-collection-%EC%9D%B4%EB%9E%80</guid>
            <pubDate>Mon, 15 Feb 2021 15:04:33 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[PostgreSQL 설치 및 사용하기]]></title>
            <link>https://velog.io/@be-lgreen/PostgreSQL-%EC%84%A4%EC%B9%98-%EB%B0%8F-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@be-lgreen/PostgreSQL-%EC%84%A4%EC%B9%98-%EB%B0%8F-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0</guid>
            <pubDate>Mon, 15 Feb 2021 09:44:12 GMT</pubDate>
            <description><![CDATA[<h3 id=""></h3>
<p>POSTRES_HOME
PGDATA (PostgreSQL의 DB Data 폴더)
LD_LIBRARY_PATH
HBA_FILE(PostgreSQL의 접근제어 파일 pg_hda.conf)</p>
<h3 id="설치">설치</h3>
<p>압축파일 다운로드
압축파일 해제
폴더이동 (.configure 파일이 있음)
.configure --prefix=/db/pgsql (--prefix : 설치 경로 설정)
make
make check
make install</p>
<ul>
<li>root가 아닌 환경변수 설정 완료 및 파일 소유 계정으로 설치 권고</li>
</ul>
<h3 id="설치-후">설치 후</h3>
<h4 id="initdb생성">initdb생성</h4>
<p>initdb를 하면 환경변수 PGDATA에 설정된 경로에 디비를 생성한다.
/db/pgsql/data</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Ansible - Roles에 대해 알아보자]]></title>
            <link>https://velog.io/@be-lgreen/Ansible-Roles%EC%97%90-%EB%8C%80%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90</link>
            <guid>https://velog.io/@be-lgreen/Ansible-Roles%EC%97%90-%EB%8C%80%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90</guid>
            <pubDate>Mon, 15 Feb 2021 09:32:43 GMT</pubDate>
            <description><![CDATA[<h3 id="roles란">Roles란</h3>
<p>파일 구조를 기반으로 관련된 vars_file, task, handler등을 자동으로 불러오는 모듈(?)의 개념이다. roles을 정의해두면 하나의 모듈처럼 재사용하거나 공유할 수 있다. </p>
<p>###</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Ansible - become, remote user]]></title>
            <link>https://velog.io/@be-lgreen/Ansible-become-remote-user</link>
            <guid>https://velog.io/@be-lgreen/Ansible-become-remote-user</guid>
            <pubDate>Mon, 15 Feb 2021 07:49:57 GMT</pubDate>
            <description><![CDATA[<p>become : sudo, su와 비슷하게 root권한이나 다른유저의 권한으로 실행하는것
remote-user : 가상 머신에 로그인하는 유저</p>
<p>로그인한 user와 다른권한으로 명령어를 실행하고자할때 사용한다. 예를들어 root권한이 아닌 user로 로그인후, root권한으로 특정 명령어를 실행하고 싶을때 사용할 수 있다. (System service의 경우 root권한을 필요로하기 때문에 이런경우에 사용할 수 있음. 아래 예제 코드 있음)</p>
<h3 id="become-사용하기">become 사용하기</h3>
<p>task directives(지시어), connection variables, command line에서 become을 사용할 수 있으며, 여러 방법을 사용하였을 경우 &#39;기본 우선 순위 규칙&#39;에 따라 적용된다.</p>
<p>우선 순위 규칙은 다음과 같다.</p>
<ol>
<li>comfiguration setting : ansible.cfg에서 설정하는 경우</li>
<li>command-line options : playbook실행 시, command line에서 옵션을 넣어주는 경우</li>
<li>playbook keywords</li>
<li>variables</li>
</ol>
<p>1 2 3 4의 방법으로 중복으로 설정되었을경우 4번이 가장 우선순위를 가진다.</p>
<h4 id="become-directives을-이용한-방법">become directives을 이용한 방법</h4>
<p>become : yes / privilege escalation을 활성화
become_user : 특정 권한으로 실행 / 기본값은 root</p>
<pre><code>- name: Ensure the httpd service is running
  service:
    name: httpd
    state: started
  become: yes</code></pre><pre><code>- name: Run a command as the apache user
  command: somecommand
  become: yes
  become_user: apache</code></pre><p>sudo를 위해 password를 지정하고 싶을때는 playbook실행 시(ansible-playbook), --ask-become-pass (-k)옵션을 주면된다.</p>
<h4 id="connection-variables을-이용한-방법">connection variables을 이용한 방법</h4>
<p>inventory에 변수를 정의하거나, 일반 변수를 사용하듯이 사용하면 된다.</p>
<p>연결은 manager유저로, 실행은 모두 root권한으로 하고 싶을경우 inventory entry</p>
<pre><code>webserver ansible_user=manager ansible_become=yes</code></pre><h4 id="command-line을-이용한-방법">command line을 이용한 방법</h4>
<h4 id="ansible에서-become사용시-주의점">ansible에서 become사용시 주의점</h4>
<p>프로그램을 설치할 target host들에 작성해둔 ansible을 복사한후 실행할 것이다. 
manager유저로 접속한 후 root로 명령어를 수행하는경우 (become_user = root), 또는 root유저로 접속한 후 root로 명령어를 수행하는 경우에는 문제가 없다.
하지만 become_user가 제3의 유저일 경우 이야기가 달라진다. ansible파일에 대한 접근권한은 connection user, root user이기 때문에 ansible파일을 실행할 수 없는 상황이 생긴다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[basic] c++ 함수 정리]]></title>
            <link>https://velog.io/@be-lgreen/basic-c-%ED%95%A8%EC%88%98-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@be-lgreen/basic-c-%ED%95%A8%EC%88%98-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Fri, 08 Jan 2021 16:34:05 GMT</pubDate>
            <description><![CDATA[<h3 id="vector">vector</h3>
<blockquote>
<p>//10짜리 0으로 초기화</p>
</blockquote>
<pre><code>vector&lt;int&gt; v(10, 0); </code></pre><blockquote>
<p>//초기화 하여 선언</p>
</blockquote>
<pre><code>vector&lt; vector&lt;int&gt; &gt; v{{1},{2, 3},{4}}</code></pre><h3 id="map">map</h3>
<blockquote>
</blockquote>
<pre><code>#include &lt;map&gt;
&gt;
map&lt;int, int&gt; m;
m.insert(make_pair(a, b));
&gt;
map&lt;int, int&gt;::iterator iter;
for(int i=0; i&lt;nums.size(); i++){
    iter = m.find(c);
    if(iter != m.end() &amp;&amp; (*iter).second != d){
        // do something              
    }
}</code></pre><blockquote>
</blockquote>
<h3 id="정렬">정렬</h3>
<blockquote>
</blockquote>
<pre><code>sort(v.begin(), v.end())</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[basic] LIS - Binary Search]]></title>
            <link>https://velog.io/@be-lgreen/basic-LIS-Binary-Search</link>
            <guid>https://velog.io/@be-lgreen/basic-LIS-Binary-Search</guid>
            <pubDate>Fri, 08 Jan 2021 16:04:36 GMT</pubDate>
            <description><![CDATA[<pre><code>#include &lt;iostream&gt;
#include &lt;vector&gt;
using namespace std;

int LIS2(vector&lt;int&gt; &amp;v){
    vector&lt;int&gt; answer;
    answer.push_back(v[0]);

    for(int i=1; i&lt;v.size(); i++){
        if(v[i] &gt; answer.back()){
            answer.push_back(v[i]);
        }else{
            vector&lt;int&gt;::iterator iter = lower_bound(answer.begin(), answer.end(), v[i]);
            *iter = v[i];
        }
    }

    return answer.size();
}


int LIS1(vector&lt;int&gt; &amp;v){
    vector&lt;int&gt; answer;
    answer.push_back(v[0]);

    for(int i=1; i&lt;v.size(); i++){
        if(v[i] &gt; answer.back()){
            answer.push_back(v[i]);
        }else{
            //find lower bound using binary search
            int left = 0;
            int right = answer.size() - 1;
            int mid;
            while(right - left &gt; 0){
                mid = left + (right - left) / 2;
                if(answer[mid] &gt;= v[i]){
                    right = mid;
                }else{
                    left = mid + 1;
                }
            }
            answer[left] = v[i];
        }
    }

    return answer.size();
}

int main(){
    vector&lt;int&gt; v1 = {1, 2, 3, 2, 3, 4, 9, 4, 5}; // answer : 5
    vector&lt;int&gt; v2 = {10, 20, 40, 25, 20, 50, 30, 70, 80}; // answer : 6

    cout &lt;&lt; LIS1(v1) &lt;&lt; endl;
    cout &lt;&lt; LIS2(v1) &lt;&lt; endl;

    cout &lt;&lt; LIS1(v2) &lt;&lt; endl;
    cout &lt;&lt; LIS2(v2) &lt;&lt; endl;
}
</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[basic] FloydWarshall]]></title>
            <link>https://velog.io/@be-lgreen/basic-FloydWarshall</link>
            <guid>https://velog.io/@be-lgreen/basic-FloydWarshall</guid>
            <pubDate>Fri, 08 Jan 2021 16:03:34 GMT</pubDate>
            <description><![CDATA[<pre><code>#include &lt;iostream&gt;
#include &lt;vector&gt;
using namespace std;

vector&lt;vector&lt;int&gt; &gt; floydWarshall(vector&lt;vector&lt;int&gt; &gt; &amp;v) {
    int n = v.size();
    vector&lt;vector&lt;int&gt; &gt; d(n, vector&lt;int&gt;(n, 0));

    for(int i = 0; i &lt; n; i++){
        for(int j = 0; j &lt; n; j++){
            d[i][j] = v[i][j];
        }
    }

    // k = 거쳐 가는 노드
    for (int k = 0; k &lt; n; k++) {
        // i = 출발 노드
        for (int i = 0; i &lt; n; i++) {
            // j = 도착 노드
            for (int j = 0; j &lt; n; j++) {
                if (d[i][k] + d[k][j] &lt; d[i][j])
                    d[i][j] = d[i][k] + d[k][j];
            }
        }
    }

    return d;
}

void printSolution(vector&lt;vector&lt;int&gt; &gt; &amp;v){
    int n = v.size();
    for (int i = 0; i &lt; n; i++){
        for (int j = 0; j &lt; n; j++) {
            cout &lt;&lt; v[i][j] &lt;&lt; &quot; &quot;;
        }
        cout &lt;&lt; endl;
    }
    cout &lt;&lt; endl;
}


int main() {
    const int INF = 1000000000;
    vector&lt;vector&lt;int&gt; &gt; v1{
        {0,   2,   5, 1,   INF, INF},
        {2,   0,   3, 2,   INF, INF},
        {5,   3,   0, 3,   1,   5},
        {1,   2,   3, 0,   1,   INF},
        {INF, INF, 1, 1,   0,   2},
        {INF, INF, 5, INF, 2,   0}
    };

    vector&lt;vector&lt;int&gt; &gt; v2{
        {0,   5,  INF, 10},
        {INF,  0,  3,  INF},
        {INF, INF, 0,   1},
        {INF, INF, INF, 0}
    };

    vector&lt;vector&lt;int&gt; &gt; answer = floydWarshall(v1);
    printSolution(answer);

    answer = floydWarshall(v2);
    printSolution(answer);

    return 0;
}
</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[basic] Lower Bound]]></title>
            <link>https://velog.io/@be-lgreen/basic</link>
            <guid>https://velog.io/@be-lgreen/basic</guid>
            <pubDate>Fri, 08 Jan 2021 16:01:02 GMT</pubDate>
            <description><![CDATA[<p>reference : <a href="https://www.geeksforgeeks.org/implementing-upper_bound-and-lower_bound-in-c/">https://www.geeksforgeeks.org/implementing-upper_bound-and-lower_bound-in-c/</a></p>
<pre><code>#include &lt;iostream&gt;
#include &lt;vector&gt;
using namespace std;

int lower_bound(vector&lt;int&gt; &amp;v, int target){
    int left = 0;
    int right = v.size() - 1;
    int mid;

    while(right - left &gt; 0){
        //mid = (right + left) / 2;
        mid = left + (right - left) / 2;

        if(target &lt;= v[mid]){
            right = mid;
        }else{
            left = mid + 1;
        }
    }

    return left;
}

int upper_bound(vector&lt;int&gt; &amp;v, int target){
    int left = 0;
    int right = v.size() - 1;
    int mid;

    while(right - left &gt; 0){
        mid = left + (right - left) / 2;

        if(target &lt; v[mid]){  // difference with lower_bound
            right = mid;
        }else{
            left = mid + 1;
        }
    }

    return left;
}

int main(){
    vector&lt;int&gt; v = {10, 10, 20, 20, 20, 20, 40};
    vector&lt;int&gt; v2 = {1, 2, 3};
    int num = 20;
    int num2 = 2;

    cout &lt;&lt; lower_bound(v, num) &lt;&lt; endl;
    cout &lt;&lt; lower_bound(v2, num2) &lt;&lt; endl;

    cout &lt;&lt; upper_bound(v, num) &lt;&lt; endl;
    cout &lt;&lt; upper_bound(v2, num2) &lt;&lt; endl;

}</code></pre>]]></description>
        </item>
    </channel>
</rss>