Difference between r1.177 and the current
@@ -144,11 +144,11 @@
=== 쿠버네티스에 첫 번째 애플리케이션 실행하기 ===
* p97
* 쿠버네티스는 개별 컨테이너들을 직접 다루지 않는다. 대신 함꼐 배치된 다수의 컨테이너라는 개념을 사용한다. 이 컨테이너의 그룹의 이름을 파드라고 한다.
* 쿠버네티스는 개별 컨테이너들을 직접 다루지 않는다. 대신 함께 배치된 다수의 컨테이너라는 개념을 사용한다. 이 컨테이너의 그룹의 이름을 파드라고 한다.
* POD는 여러개의 컨테이너가 들어갈수 있음. - [김준석]* 각 파드는 자체 IP, 호스트 이름, 프로세스 등이 있는 논리적으로 분리된 머신이다.
* 머신이지만 os가 없는 느낌? 자원관리 등을 다 상위에서 해주니 논리적으로 머신이기만 함 - [김준석]
* 요건 오해의 소지가 있는 설명이긴 하네요. 이해를 돕기위해 의도적인 왜곡인것 같긴 하지만... - [bluemir]
* p98* ` kubectl get pods `
* kgp - [김준석]
@@ -160,10 +160,10 @@
* 서비스 할당? - [김준석]
* 파드와 마찬가지로 일반적인 서비스(Cluster IP 서비스)를 생성하면 이것은 클러스터 내부에서만 접근 가능하기 때문에 Load Balancer 유형의 특별한 서비스를 생성해야 한다.
* 로드밸런서 생성은 처음 본듯 - [김준석]
* 외부에서 Traffic 받을려면 가장 simple한 방법이라... 오히려 node port 방식이 더 드물긴 합니다. - [bluemir]
* {{{ kubectl expose rc kubia --type=LoadBalancer --name kubia-http }}}
* {{{ kubernetes 서비스에 관한 설명은 생략 }}}
* kubectl run 명령을 수행하면 레플리케이션컨트롤러를 생성하고 레플리케이션컨트롤러가 실제 파드를 생성한다.
* 띄어쓰기 좀.. - [서지혜]
* 파드와 마찬가지로 일반적인 서비스(Cluster IP 서비스)를 생성하면 이것은 클러스터 내부에서만 접근 가능하기 때문에 Load Balancer 유형의 특별한 서비스를 생성해야 한다.
* 로드밸런서 생성은 처음 본듯 - [김준석]
* 외부에서 Traffic 받을려면 가장 simple한 방법이라... 오히려 node port 방식이 더 드물긴 합니다. - [bluemir]
* p101 * ` kubectl expose rc kubia --type= LoadBalancer --name kubia-http `
* ` kubernetes 서비스에 관한 설명은 생략 `
* p103* kubectl run 명령을 수행하면 레플리케이션컨트롤러를 생성하고 레플리케이션컨트롤러가 실제 파드를 생성한다.
* 띄어쓰기 좀.. - [서지혜]
@@ -173,19 +173,17 @@
* 파드는 일시적(ephermeral)이다.
* 새로운 파드는 다른 IP 주소를 할당받는다. 이것이 바로 서비스가 필요한 이유다.
* p106
* 서비스는 다수 파드 앞에서 로드밸런서 역할을 한다. 파드가 하나만 있으면 서비스는 이 파드 하나에 정적 주소를 제공한다.
* p109
* 어떤 노드에 파드가 스케줄링됐는지 궁금할 수 있다. 쿠버네티스에서는 파드가 적절히 실행하는 데 필요한 CPU와 메모리를 제공하는 노드에 스케줄링됐다면, 어떤 노드에 파드가 실행 중인지는 중요하지 않다.
* 파드를 조회할 때 파드 IP와 실행 중인 노드 표시하기
* {{ $ kubectl get pods -o wide }}}
* p110
* 쿠버네티스 또한 꽤 멋진 웹 대시보드를 함께 제공한다는 점을 알게 되면 기뻐할 것이다.
* 실제로 하드하게 써보면 별로 안기쁘더라구요 - [bluemir]
=== 파드 소개 ===
* p114
* 새로운 파드는 다른 IP 주소를 할당받는다. 이것이 바로 서비스가 필요한 이유다.
* p106
* {{{ kubectl scale rc kubia --replicas=3 }}}
* {{{ kubectl get rc }}}
* ` kubectl scale rc kubia --replicas=3 `
* ` kubectl get rc `
* p107* 서비스는 다수 파드 앞에서 로드밸런서 역할을 한다. 파드가 하나만 있으면 서비스는 이 파드 하나에 정적 주소를 제공한다.
* 어떤 노드에 파드가 스케줄링됐는지 궁금할 수 있다. 쿠버네티스에서는 파드가 적절히 실행하는 데 필요한 CPU와 메모리를 제공하는 노드에 스케줄링됐다면, 어떤 노드에 파드가 실행 중인지는 중요하지 않다.
* 파드를 조회할 때 파드 IP와 실행 중인 노드 표시하기
* {{ $ kubectl get pods -o wide }}}
* p110
* 쿠버네티스 또한 꽤 멋진 웹 대시보드를 함께 제공한다는 점을 알게 되면 기뻐할 것이다.
* 실제로 하드하게 써보면 별로 안기쁘더라구요 - [bluemir]
== 파드: 쿠버네티스에서 컨테이너 실행 ===== 파드 소개 ===
* p114
@@ -471,7 +469,7 @@
* p245
* 인그레이스는 비교적 새로운 쿠버네티스 기능이므로 향후 많은 개선과 새로운 기능를 기대할 수 있다.
* https://kubernetes.io/docs/reference/using-api/deprecation-guide/#ingress-v122 1.19까지 사용가능하고 deprecated됨? - [김준석]
* istio 나 기타 다른 Ingress 발전속도가 워낙 빨라서 k8s Ingress spec을 update 속도가 못따라가서 그렇습니다. k8s Ingress Spec으로는 안되는기능이 너무 많아요. 지금 대세는 Istio를 쓰는 것입니다(Istio가 Ingress기능만 하는건 아닙니다.) - [bluemir]
* p246
* 쿠버네티스에서는 라이브니스 프로브와 비슷하게 파드에 레디니스 프로브를 정의할 수 있다.
* 인그레이스는 비교적 새로운 쿠버네티스 기능이므로 향후 많은 개선과 새로운 기능를 기대할 수 있다.
* https://kubernetes.io/docs/reference/using-api/deprecation-guide/#ingress-v122 1.19까지 사용가능하고 deprecated됨? - [김준석]
* istio 나 기타 다른 Ingress 발전속도가 워낙 빨라서 k8s Ingress spec을 update 속도가 못따라가서 그렇습니다. k8s Ingress Spec으로는 안되는기능이 너무 많아요. 지금 대세는 Istio를 쓰는 것입니다(Istio가 Ingress기능만 하는건 아닙니다.) - [bluemir]
=== 파드가 연결을 수락할 준비가 됐을 때 신호 보내기 ===* p246
* 쿠버네티스에서는 라이브니스 프로브와 비슷하게 파드에 레디니스 프로브를 정의할 수 있다.
@@ -512,6 +510,7 @@
* p263
* 볼륨을 채우거나 마운트하는 프로세스는 파드의 컨테이너가 시작되기 전에 수행된다.
* preload같은? 이거 컨테이너의 init 보다 먼저인가? - [김준석]
* emptyDir
* hostPath
* 볼륨을 채우거나 마운트하는 프로세스는 파드의 컨테이너가 시작되기 전에 수행된다.
* preload같은? 이거 컨테이너의 init 보다 먼저인가? - [김준석]
* initContainer 보다 먼저입니다. 여기서 말하는 Process 는 VolumeDriver의 Process인듯 하네요(fuse 같은거요). - [bluemir]
* 다양한 유형의 볼륨이 사용 가능하다.* emptyDir
* hostPath
@@ -539,6 +538,7 @@
* 사이트카 컨테이너 소개
* 새로운 로직을 메인 애플리케이션 코드에 밀어 넣어 복잡성을 더하고 재사용성을 떨어뜨리는 대신에 파드에 사이드카를 추가하면 기존 컨테이너 이미지를 사용할 수 있다.
* 이런거 좀 해설좀 자세히 해줬으면. 사이드카와 메인nginx사이 같은 공유공간을 가지고 있는데 사이드카 컨테이너가 gitRepo 볼륨을 가지고 주기적으로 밀어넣어서 웹페이지를 갱신한단 소리겠지? - [김준석]
* 프라이빗 깃 리포지터리를 컨테이너에 복제하려면.. 다른 유사 방법을 사용해야 한다
=== 워커 노드 파일시스템의 파일 접근 ===
* 새로운 로직을 메인 애플리케이션 코드에 밀어 넣어 복잡성을 더하고 재사용성을 떨어뜨리는 대신에 파드에 사이드카를 추가하면 기존 컨테이너 이미지를 사용할 수 있다.
* 이런거 좀 해설좀 자세히 해줬으면. 사이드카와 메인nginx사이 같은 공유공간을 가지고 있는데 사이드카 컨테이너가 gitRepo 볼륨을 가지고 주기적으로 밀어넣어서 웹페이지를 갱신한단 소리겠지? - [김준석]
* 그것보단 log stash 같은 로그 수집기를 한 Container 내에 넣는 대신 별개의 Container 로 분리하면 나중에 Log 설정을 바꿔야 할떄 Application Container를 바꾸는대신 별개의 logstash sidecar를 바꾸면 된다는 의미입니다. 예시는 log 지만 Network관련 설정이나 Monitoring 설정등도 가능합니다. 또한 Cluster Provider 가 Sidecar inject를 제공하는 경우 Sidecar의 버전등이 Application 과는 완전 별개로 돌아 갈수 있으므로 Applicaiton 개발자와 Cluster Provider의 마찰도 줄일수 있습니다. 이런 구조를 가장 잘 활용하는것은 Istio(service mesh)가 있습니다.- [bluemir]
* p272* 프라이빗 깃 리포지터리를 컨테이너에 복제하려면.. 다른 유사 방법을 사용해야 한다
=== 워커 노드 파일시스템의 파일 접근 ===
@@ -823,6 +823,7 @@
* 이건 개발자들이 실행할때만 안다는 그것 - [김준석]
* 마스터 노드에는 시크릿을 암호화되지 않은 형식으로 저장하므로, 시크릿에 저장한 민감한 데이터를 보호하려면 마스터 노드를 보호하는 것이 필요하다.(base64로 인코딩으로 바뀜)
* base64로 인코딩해서 보관한다던데 - [김준석]
* 시크릿이 갖고 있는 세 가지 항목은 파드 안에서 쿠버네티스 API 서버와 통신할 때 필요한 모든 것을 나타낸다.
* p341
* 마스터 노드에는 시크릿을 암호화되지 않은 형식으로 저장하므로, 시크릿에 저장한 민감한 데이터를 보호하려면 마스터 노드를 보호하는 것이 필요하다.(base64로 인코딩으로 바뀜)
* base64로 인코딩해서 보관한다던데 - [김준석]
* api server option에 etcd에 저장시 암호화 적용을 할수 있는 옵션은 있습니다. 다만 `kubectl get secret` 하면 원본이 보이기 떄문에 아무나 API server에 접근 하지 못하도록 보호하라는 의미인것 같네요. - [bluemir]
* p339* 시크릿이 갖고 있는 세 가지 항목은 파드 안에서 쿠버네티스 API 서버와 통신할 때 필요한 모든 것을 나타낸다.
* p341
@@ -982,6 +983,7 @@
* p392
* 새 파드 모두 실행되면 그림과 같이 서비스의 레이블 셀렉터를 변경하고 서비스를 새 파드로 전환할 수 있다. 이것을 블루-그린 디플로이먼트라고 한다.
* 블루 그린은 또 무슨뜻일까 - [김준석]
* 기본 설명 - [김준석]
* 새 파드 모두 실행되면 그림과 같이 서비스의 레이블 셀렉터를 변경하고 서비스를 새 파드로 전환할 수 있다. 이것을 블루-그린 디플로이먼트라고 한다.
* 블루 그린은 또 무슨뜻일까 - [김준석]
* 배포전략중 하나입니다. https://martinfowler.com/bliki/BlueGreenDeployment.html - [bluemir]
* 새 파드가 모두 실행된 후 이전파드를 한 번에 삭제하는 방법 대신 파드를 단계별로 교체하는 롤링 업데이트를 수행할 수도 있다.* 기본 설명 - [김준석]
@@ -1205,6 +1207,7 @@
* p487
* API서버는 이런 커트롤러에 무엇을 해야 하는지 알려주지 않는다. 단지 컨트롤러와 다른 구성 요소가 배포된 리소스의 변경 사항을 관찰할 수 있도록 하면 된다.
* 클라이언트는 API 서버에 http 연결을 맺고 변경 사항을 감지한다. 이 연결을 통해 클라이언트 감시 대상 오브젝트의 변경을 알 수 있는 스트림을 받는다. 오브젝트가 갱신될 때마다, 서버는 오브젝트를 감시하고 있는 연결된 모든 클라이언트에게 오브젝트의 새로운 버전을 보낸다.
==== 스케줄러 이해 ====
* p489
* API서버는 이런 커트롤러에 무엇을 해야 하는지 알려주지 않는다. 단지 컨트롤러와 다른 구성 요소가 배포된 리소스의 변경 사항을 관찰할 수 있도록 하면 된다.
* 클라이언트는 API 서버에 http 연결을 맺고 변경 사항을 감지한다. 이 연결을 통해 클라이언트 감시 대상 오브젝트의 변경을 알 수 있는 스트림을 받는다. 오브젝트가 갱신될 때마다, 서버는 오브젝트를 감시하고 있는 연결된 모든 클라이언트에게 오브젝트의 새로운 버전을 보낸다.
* 저는 GRPC 연결이라고 알고 있는데 과거에는 달랐을수도 있겠네요 - [bluemir]
==== 스케줄러 이해 ====
* p489
@@ -1581,7 +1584,7 @@
* Mi는 이진주 시반의 Mebibyte를 의미한다. MB(megabyte)는 십진수 기반으로 차이가 있다.
* p611
* CPU 요청을 지정하지 않으면 ... 최악의 경우 CPU 시간을 전혀 할당받지 못할 수 있다.
* request는 최소 할당 리소스, limits는 최대 할당 리소스 - [서지혜]
* {{{ $ kubectl exec -it requrests-pod top }}}
* p611
* CPU 요청을 지정하지 않으면 ... 최악의 경우 CPU 시간을 전혀 할당받지 못할 수 있다.
* request 가 매우 낮을경우에도 발생합니다. 10m~50m 으로 설정했다가 1~5초 정도의 delay를 겪을수도 있습니다.
* request 가 매우 낮을경우에도 발생합니다. 10m~50m 으로 설정했다가 1~5초 정도의 delay를 겪을수도 있습니다. - [bluemir]
* 요청(request)는 컨테이너가 사용할 수 있는 CPU 양을 제한하지 않으므로 이는 예견된 일이다. 제한을 하려면 CPU 제한(limits)을 지정해야 한다.* request는 최소 할당 리소스, limits는 최대 할당 리소스 - [서지혜]
* {{{ $ kubectl exec -it requrests-pod top }}}
@@ -1597,21 +1600,26 @@
* p617
* kube-system 네임스페이스의 세 파드가 명시적으로 CPU 리소스를 요청했다. 이 요청이 노드를 오버커밋 하게 만들기 때문에 스케줄러는 노드에 파드를 스케줄링 할 수 없다.
* 노드 용량 초과를 overcommit이라고 하는군 - [서지혜]
* CPU 요청에 기반해 사용되지 않은 CPU시간이 컨테이너에 분배된다.
* 제한을 두지 않은 파드들이 유휴상태가 아니라면 남는 CPU 시간은 파드들의 요청에 비례해 분배된다 - [서지혜]
* 역시 그렇군 - [서지혜]
* 쿠버네티스를 사용하면 사용자 정의 리소스를 노드에 추가하고 파드의 리소스 요청으로 사용자 정의 리소스를 요청할 수 있다.
* 리소스 이름은 kubernetes.io 도메인으로 시작하지 않는 이상 example.org/my-resource 와 같이 무엇이든 될수 있다. 수량은 반드시 정수여야 한다. 이값은 capacity 필드에서 allocatable 필드로 자동으로 복사된다.
* 사용자 정의 리소스의 예로는 노드에 사용 가능한 GPU 단위 수가 있다.
=== 컨테이너에 사용 가능한 리소스 제한 ===
* p620
* CPU 사용률은 조절되므로 컨테이너에 CPU 제한이 설정돼 있으면 프로세스는 설정된 제한보다 많은 CPU 시간을 할당받을 수 없다.
* 메모리는 CPU와는 다르다. 프로세스가 제한보다 많은 메모리를 할당받으려 시도하면 프로세스는 종료된다(컨테이너가 OOMKilled 됐다고 한다. OOM은 Out Of Memory다) 파드의 재시작 정책이 Always 또는 OnFailure로 설정된 경우 프로세스는 즉시 다시 시작하므로 종료됐음을 알아차리지 못할 수 있다.
* kube-system 네임스페이스의 세 파드가 명시적으로 CPU 리소스를 요청했다. 이 요청이 노드를 오버커밋 하게 만들기 때문에 스케줄러는 노드에 파드를 스케줄링 할 수 없다.
* 노드 용량 초과를 overcommit이라고 하는군 - [서지혜]
* 또는 Overprovisioning 이라고도 합니다. - [bluemir]
* p619* CPU 요청에 기반해 사용되지 않은 CPU시간이 컨테이너에 분배된다.
* 제한을 두지 않은 파드들이 유휴상태가 아니라면 남는 CPU 시간은 파드들의 요청에 비례해 분배된다 - [서지혜]
* 이 분배 비율은 request에 영향을 받는것으로 알고 있습니다. cgroup의 동작이 그러한것으로 알아요 - [bluemir]
* 결국 아무도 사용하지 않는다면 사용 가능한 모든 CPU를 사용하는 것이 상식이다.* 역시 그렇군 - [서지혜]
* 쿠버네티스를 사용하면 사용자 정의 리소스를 노드에 추가하고 파드의 리소스 요청으로 사용자 정의 리소스를 요청할 수 있다.
* 리소스 이름은 kubernetes.io 도메인으로 시작하지 않는 이상 example.org/my-resource 와 같이 무엇이든 될수 있다. 수량은 반드시 정수여야 한다. 이값은 capacity 필드에서 allocatable 필드로 자동으로 복사된다.
* 사용자 정의 리소스의 예로는 노드에 사용 가능한 GPU 단위 수가 있다.
* local disk의 용량등으로 정해서 사용할수도 있습니다. - [bleumir]
=== 컨테이너에 사용 가능한 리소스 제한 ===
* p620
* CPU는 압축 가능한 리소스다. 즉, 컨테이너에서 실행 중인 프로세스에 부정적인 영향을 주지 않고 컨테이너가 사용하는 CPU 양을 조절할 수 있따. 메모리는 분명 다르다. 프로세스에 메모리가 주어지면 프로세스가 메모리를 해제하지 않는 한 가져갈 수 없다.
* CPU는 압축 가능한 리소스다. 즉, 컨테이너에서 실행 중인 프로세스에 부정적인 영향을 주지 않고 컨테이너가 사용하는 CPU 양을 조절할 수 있다. 메모리는 분명 다르다. 프로세스에 메모리가 주어지면 프로세스가 메모리를 해제하지 않는 한 가져갈 수 없다.
* 압축 가능한 리소스라는게 생소하군요 - [서지혜]
* p621 * 오작동하거나 악의적인 파드 하나가 실제 전체 노드를 사용할 수 없게 만들 수 있다.
* 리소스 모니터링이 필요한 이유 - [서지혜]
* 리소스 요청과는 달리 리소스 제한은 노드의 할당 가능한 리소스 양으로 제한되지 않는다. 모든 파드의 리소스 제한 합계는 노드 용량의 100%를 초과할 수 있다.* CPU 사용률은 조절되므로 컨테이너에 CPU 제한이 설정돼 있으면 프로세스는 설정된 제한보다 많은 CPU 시간을 할당받을 수 없다.
* 메모리는 CPU와는 다르다. 프로세스가 제한보다 많은 메모리를 할당받으려 시도하면 프로세스는 종료된다(컨테이너가 OOMKilled 됐다고 한다. OOM은 Out Of Memory다) 파드의 재시작 정책이 Always 또는 OnFailure로 설정된 경우 프로세스는 즉시 다시 시작하므로 종료됐음을 알아차리지 못할 수 있다.
@@ -1676,9 +1684,268 @@
* p645
* Kubelet 자체에는 이미 cAdvisor라는 에이전트가 포함돼 있는데 이 에이전트는 노드에서 실행되는 개별 컨테이너와 노드 전체의 리소스 사용 데이터를 수집한다. 전체 클러스터를 이러한 통계를 중앙세ㅓ 수집하려면 힙스터라는 추가 구성요소를 실행해야 한다.
* 힙스터가 사라지고 cAdvisor가 대체된것으로 앎 - [김준석]
== 파드와 클러스터 노드의 오토스케일링 ==
== 쿠버네티스의 확장 ==
* Kubelet 자체에는 이미 cAdvisor라는 에이전트가 포함돼 있는데 이 에이전트는 노드에서 실행되는 개별 컨테이너와 노드 전체의 리소스 사용 데이터를 수집한다. 전체 클러스터를 이러한 통계를 중앙세ㅓ 수집하려면 힙스터라는 추가 구성요소를 실행해야 한다.
* 힙스터가 사라지고 cAdvisor가 대체된것으로 앎 - [김준석]
* 맞습니다 지금은 그냥 cAdvisor 를 쓰는게 defacto 같아요. - [bluemir]
* {{{ $ kubectl top pod --all-namespaces }}}== 파드와 클러스터 노드의 오토스케일링 ==
* p655
* 파드에서 실행되는 애플리케이션은 레플리케이션컨트롤러, 레플리카셋, 디플로이먼트 또는 기타 확장 가능한 리소스 안에 있는 replicas 필드 값을 늘려 수동으로 확장할 수 있다.
* 쿠버네티스는 파드를 모니터링하다가 CPU 사용량이나 다른 메타륵이 증가하는 것을 감지하는 즉시 자동으로 확장할 수 있다.
=== 수평적 파드 오토스케일링 ===
* p656
* 수평적 파드 오토스케일링은 컨트롤러가 관리 파드의 레플리카 수를 자동으로 조정하는것을 말한다.
* 이것은 Horizontal 컨트롤러에 의해 수행되며, HorizontalPodAutoscaler(HPA) 리소스를 작성해 활성화시키고 원하는 대로 설정한다.
* 컨트롤러는 주기적으로 파드 메트릭을 확인해, HorizontalPodAutoscaler 리소스에 설정돼 있는 대상 메트릭 값을 만족하는 레플리카 수를 계산한다.
* 그리고 대상 리소스 안에 있는 replicas 필드 값을 조절한다.
* 오토스케일링 프로세스는 세 단계로 나눌 수 있다.
* 확장 가능한 리소스 오브젝트에서 관리하는 모든 파드의 메트릭을 가져온다.
* 메트릭을 지정한 목표 값과 같거나 가깝도록 하기 위해 필요한 파드 수를 계산한다.
* 확장 가능한 리소스의 replicas 필드를 갱신한다.
* 파드와 노드 메트릭은 모든 노드에서 실행되는 kubelet에서 실행되는 cAdvisor 에이전트에 의해 수집된다.
* p658
* 오토스케일러의 스케일링 대상이 되는 리소스에 속해 있는 파드의 모든 메트릭을 가지고 있으면, 이 메트릭을 사용해 필요한 레플리카 수를 파악할 수 있다. 모든 레플리카에서 메트릭의 평균 값을 이용해 지정한 목표값과 가능한 가깝게 하는 숫자를 찾아야 한다. 이 계산의 입력은 파드 메트릭 세트이고, 출력은 하나의 정수이다.
* 오토스케일링이 여러 파드 메트릭(CPU 사용량, 초당 질의수(QPS))을 기반으로 하는 경우 계산이 그렇게 복잡하지는 않다. 오토스케일러는 각 메트릭의 레플리카 수를 개별적으로 계산한 뒤 가장 높은 값을 취한다.
* p659
* 오토스케일링 자겁의 마지막 단계는 스케일링된 리소스 오브젝트의 레플리카 개수 필드를 원하는 값으로 갱신해, 레플리카셋 컨트롤러가 추가 파드를 시작하거나 초과한 파드를 삭제하도록 하는 것이다.
* API 서버가 스케일 서브 리소스를 노출하는 한, 오토스케일러는 모든 확장 가능한 리소스를 대상으로 동작할 수 있다. 현재 노출되는 리소스는 다음과 같다.
* 디플로이먼트
* 레플리카셋
* 레플리케이션컨트롤러
* 스테이트풀셋
* p660
* CPU 사용률 기반 스케일링
* CPU 사용량이 100%에 도달하면 더 이상 요구에 대응할 수 없어 스케일 업(수직적 스케일링: 파드가 사용하는 CPU 양 증가)이나 스케일 아웃(수평적 스케일링: 파드 수 증가)이 필요하다. 여기서 우리는 수평적 파드 오토스케일러만 얘기하고 있기 때문에, 스케일 아웃에 관해서만 집중해보자. 스케일 아웃이 이루어지면 평균 CPU 사용량은 줄어들 것이다.
* 오토스케일러는 파드의 실제 CPU 사용량과 CPU 요청을 비교하는데, 이는 오토스케일링이 필요한 파드는 오토스케일러가 CPU 사용률을 결정하기 위해서 오토스케일링이 필요한 파드는 직접 또는 간접적으로 LimitRange 오브젝트를 통해 CPU 요청을 설정해야 한다는 것을 의미한다.
* p662
* {{{
$ kubectl autoscale deployment kubia --cpu-percent=30 --min=1 --max=5
// cpu 사용률 30% 유지 최소 1 최대 5
}}}
* p664
* {{{
$ kubectl get hpa
}}}
* p668
* 오토스케일러가 어떻게 네 개의 레플리카가 필요하다는 결론을 얻었는지 살펴보자. 처음에는 레플리카 한 개가 요청을 처리하면서 CPU 사용량이 108%로 급증했다. 108을 30으로 나누면 3.6을 얻게 되는ㄴ데, 오토스케일러는 이 값을 반올림해서 4로 만든다. 108을 4로 나누면 27%를 얻는다. 만약 오토스케일러가 네 개의 파드로 스케일 업하면, 파드들의 평균 CPU 사용률은 27% 근처일 것으로 예상되고, 이 값은 목표 값이 30%에 가깝고 관찰된 CPU 사용률과 거의 비슷하다.
* 한 번의 확장 단계에서 추가할 수 있는 레플리카의 수는 제한돼 있기 때문이다. 오토스케일러는 두 개를 초과하는 레플리카가 존재할 경우 한 번의 수행에서 최대 두 배의 레플리카를 생성할 수 있다.
* p669
* 메모리 기반 오토스케일링은 CPU 기반 오토스케일링에 비해 훨씬 문제가 많다. 가장 큰 이유는 스케일 업 후에 오래된 파드는 어떻게든 메모리를 해제하는 것이 필요하기 때문이다.
* p670
* 쿠버네티스 오토스케일링 SIG 는 오토스케일러를 완전히 다시 설계했다.
* p671
* HPA 오브젝트에는 사용할 수 있는 세 가지 유형의 메트릭이 있다.
* 리소스
* 파드
* 오브젝트
* 메트릭의 예로는 이미 언급했던 초당 질의 수 또는 메시지 브로커의 큐 메시지 수 등이 있다.
* p672
* Object 메트릭 유형은 오토스케일러가 파드를 확장할 때 파드에 직접 관련되지 않는 메트릭을 기반으로 하도록 만든다. 예를 들어 파드를 확장할 때 인그레스 오브젝트 같은 클러스터 오브젝트 메트릭을 이용할 수 있다.
* p673
* 앞에서 언급한 것처럼 파드에 있는 컨테이너의 메모리 소비량은 오토스케일링에 적합한 메트릭이 아니다. 레플리카 수를 늘려도 관찰 중인 메트릭의 평균 값이 선형적으로 감소하지 않거나 최소한 선형에 가깝게 줄어들지 않는다면 오토스케일러가 제대로 동작하지 않는다.
* 오토스케일러 애플리케이션 정의 메트릭을 오토스케일러의 기반 항목으로 하기 전에, 파드 수가 증가하고 감소할 때 메트릭 값이 어떻게 변화하는지 고려해야 한다.
* 수평적 파드 오토스케일러는 현재 minReplicas 필드를 0으로 설정할 수 없기 때문에, 파드가 아무것도 하지 않더라고 오토스케일러는 파드 수를 0으로 감소시키지 않는다. 파드수를 0으로 축소할 수 있게 만들면 하드웨어 사용률이 크게 높아질 수 있따.
=== 수직적 파드 오토스케일링 ===
* 수평적 확장이 불가능한 애플리케이션의 경우 유일한 옵션은 수직적(더 많은 CPU와 메모리)으로 확장하는 것이다.
* 안타깝게도 집필을 마친 지금도 수직적 파드 오토스케일링은 여전히 사용할 수 없다.
=== 수평적 클러스터 노드 확장 ===
* 모든 노드가 한계에 도달해 더 이상 파드를 추가할 수 없을 때는 어떻게 될까?
* 쿠버네티스는 추가적인 노드가 필요한 것을 탐지하면 가능한 빠르게 추가 노드를 클라우드 제공자에게 요청하는 기능을 가지고 있다.
* 실제로는 `cloud provider`라는 componemet 에게 위임합니다. 잘 알려진 제공자(GCP, AWS)가 아닌경우 cloud provider 를 직접 구현해야 해요 - [bluemir]
* 새 파드가 생성된 후 스케줄러가 기존 노드에 스케줄링할 수 없는 경우, 새로운 노드가 공급된다. 클러스터 오토스케일러는 이런 파드를 찾고 클라우드 제공자에 추가 노드를 시작하도록 요청한다.
* 클러스터 오토스케일러는 사용 가능한 노드 그룹을 검사해 최소한 하나의 노드 유형이 스케줄링되지 않은 파드를 수용할 수 있는지 확인한다.
* 클러스터 오토스케일러가 기존 노드에 스케일링할 수 없는 파드를 찾았을 때 스케일 업을 수행한다
1. 오토스케일러가 기존 노드에 스케줄할 수 없는 파드를 발견한다.
1. 오토스케일러가 어떤 노드 유형이 파드에 맞을지 결정한다. 여러 유형이 가능하다면 그중 하나를 선택한다.
1. 오토스케일러가 앞에서 선택한 노드 그룹을 스케일 업한다.
* 오토스케일러는 모든 노드에 요청된 CPU와 메모리를 모니터링해 이를 수행한다. 특정 노드에서 실행 중인 모든 파드의 CPU와 메모리 요청이 50% 미만이면 해당 노드는 필요하지 않은 것으로 간주한다. 이것이 노드를 중단하는 데 사용하는 유일한 결정 요인은 아니다. 오토스케일러는 해당 노드에서만 실행 중인 시스템 파드가 있는지 검사한다.
* 만약 시스템 파드가 노드에서 실행 중이라면 해당 노드는 종료될 수 없다. 관리되지 않는 파드나 로컬 저장소를 가진 파드가 실행되는 경우에도 마찬가지다. 만약 시스템 파드가 노드에서 실행 중이라면 해당 노드는 종료될 수 없다. 관리되지 않는 파드나 로컬 저장소를 가진 파드가 실행되는 경우에도 마찬가지다. 파드가 제공하는 서비스가 중단될 수 있기 때문이다.
* 종료할 조드를 선택되면, 해당 노드는 먼저 스케줄링할 수 없다는 표시를 하고 노드에서 실행 중인 모든 파드를 제거한다. 제거하는 모든 노드는 레플리카셋이나 다른 컨트롤러에 속해 있기 때문에, 교체할 파드가 생성되고 남아 있는 나머지 노드에 스케줄링된다.
* {{{
$ kubectl cordon <node> // 명령은 노드를 스케줄링할 수 없음으로 표시함
$ kubectl drain <node> // 명령은 노드를 스케줄링 할 수 없음으로 표시하고 노드에서 실행 중인 모든 파드를 종료한다.
}}}
* 데몬셋은 이거 무시하고 실행하던데...? - [김준석]
* 데몬셋은 모든 node에서 실행되니 Drain 하더라도 의미가 없어서 그렇습니다. - [bluemir]
* 클러스터 오토스케일러는 다음 클라우드 제공자에서 사용할 수 있다.
* 구글 쿠버네티스 엔진
* 구글 컴퓨트 엔진
* 아마존 웹 서비스
* 마이크로소프트 애저
* p679
*특정 서비스에서는 최소 개수의 파드가 항상 실행돼야 한다. 이는 쿼럼 기반 클러스터 애플리케이션인 경우 특히 그렇다. 이런 이유로 쿠버네티스는 스케일 다운 드으이 작업을 수행할 경우에도 유지돼야 하는 최소 파드 개수를 지정하는 방법을 제공한다.
== 고급 스케줄링 ==Extend Resource 이야기는 없네요.. 실무에서는 그게 유연하게 쓸수 있어서 많이쓰는데.. - [bluemir]
=== 테인트와 톨러레이션을 사용해 특정 노드에서 파드 실행 제한 ===
* p684
* 노드 테인트와 이 테인트에 대한 파드 톨러레이션이다. 테인트와 톨러레이션은 어떤 파드가 특정 노드를 사용할 수 있는지를 제한하고자 사용된다. 노드의 테인트가 허영된 경우에만 파드가 노드세 스케줄링 될 수 있다.
* 노드 셀렉터와 노드 어피니티를 사용하는 것과는 약간 다르다.
* 노드에 테인트를 추가하는 것만으로도 파드가 특정 노드에 배포되지 않도록 한다. 테인트된 노드에 배포할 파드는 테인트된 노드를 사용하게 선택할 필요가 있는 반면, 노드 셀렉터를 사용하면 파드를 배포할 노드를 명시적으로 지정한다.
* p685
* 마스터 노드에는 테인트가 하나 있따. 테인트에는 키, 값, 효과 가 있고 <key>=<value>:<effect> 형태로 표시된다.
* {{{
node-role.kubernetes.io/master <key> null <value> 효과는 NoSchedule
}}}
* 시스템 파드는 톨러레이션과 노드의 테인트가 일치하기 때문에 마스터 노드에 스케줄링 된다.
* p686
* 테인트 효과 이해하기
* kube-proxy 파드의 다른 두 가지 톨러레이션은 준비되지 않았거나 도달할 수 없는 노드에서 파드를 얼마나 오래 실행할 수 있는지를 정의한다.
* NoSchedule: 파드가 테인트를 허용하지 않는 경우 파드가 노드에 스케줄링되지 않는다.
* PreferNoSchedule: NoSchedule의 소프트한 버전이다. 즉, 스케줄러가 파드를 노드에 스케줄링하지 않으려 하지만 다른 곳에 스케줄링 할 수 없으면 해당 노드에 스케줄링 된다.
* NoExecuete: 스케줄링에만 영향을 주는 NoSchedule이나 PreferNoSchedule과 달리, NoExecute는 노드에서 이미 실행 중인 파드에도 영향을 준다. NoExecute 테인트를 노드에 추가하면 해당 노드에서 이미 실행 중이지만 NoExecute 테인트를 허용하지 않는 파드는 노드에서 제거된다.
* 노드에 사용자 정의 테인트 추가하기
{{{ $ kubectl taint node node1.k8s node-type=production:NoSchedule }}}
* 파드에 톨러레이션 추가
{{{
spec:
tolerations:
- key: node-type
Operator: Equal
value: production
effect: NoSchedule
}}}
* p689
* 테인트는 키와 효과만 갖고 있고, 값을 꼭 필요로 하지 않는다. 톨러레이션은 Equal 연산자를 지정해 특정한 값을 허용하거나, Exists 연산자를 사용해 특정 테인트 키에 여러값을 허용할 수 있다.
=== 노드 어피니티를 사용해 파드를 특정 노드로 유인하기 ===
* p691
* 노드 셀렉터와 유사하게 각 파드는 고유한 노드 어피니티 규칙을 정의할 수 있다. 이를 통해 꼭 지켜야 하는 필수 요구 사항이나 선호도를 지정할 수 있다.
* p693
* {{{
apiVersion: v1
kind: Pod
metadata:
name: kubia-gpu
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: gpu
operator: In
values:
- "true"
containers:
- image: luksa/kubia
name: kubia
}}}
* requireDuringScheduleing... 이 필드 아래에 정의된 규칙은 파드가 노드로 스케줄링되고자 가져야 하는 레이블을 지정한다.
* ...IgnoredDuringExecution 이 필드 아래에 정의된 규칙은 노드에서 이미 실행중인 파드에는 영향을 미치지 않는다.
* 현재 시점에는 어피니티가 파드 스케줄링에만 영향을 미치며, 파드가 노드에서 제거되지 않음을 알려주고싶다.
* nodeSelectorTerms 필드와 matchExpressions 필드가 파드를 노드에 스케줄링하고자 노드의 레이블이 일치하도록 표현식을 정의하는데 사용된다는 것을 쉽게 이해할 수 있을 것이다.
* p695
* 새로 도입된 노드 어피니티 기능의 가장 큰 장점을 특정 파드를 스케줄링할 때 스케줄러가 선호할 노드를 지정할 수 있다는 것이다. 이는 prefereedDuringSchedulingIgnoredDuringExecution 필드를 통해 수행된다.
* p697
{{{
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: pref
spec:
replicas: 5
template:
metadata:
labels:
app: pref
spec:
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 80
preference:
matchExpressions:
- key: availability-zone
operator: In
values:
- zone1
- weight: 20
preference:
matchExpressions:
- key: share-type
operator: In
values:
- dedicated
...
}}}
* 이 파드는 어느 노드에나 스케줄링 될 수 있지만 파드의 레이블에 따라 특정 노드를 선호한다.
* p699
* 생성된 다섯 개의 파드 중 네 개는 node1에 배포됐으나 하나는 node2에 배포됐다. 왜 파드 중 하나가 node1 대신 node2에 배포돼쓸까? 그 이유는 스케줄러가 파드를 스케줄링 할 위치를 결정하는 데 노드의 어피니티 우선순위 지정 기능 외에도 다른 우선순위 지정기능을 사용하기 때문이다. 그중 하나다 Selector-spreadPriority 기능이다. 이 기능은 동일한 레플리카셋 또는 서비스에 속하는 파드를 여러 노드에 분산시켜 노드 장애로 인해 전체 서비스가 중단되지 않도록 한다. 이는 파드 중 하나가 node2에 스케줄링된 원인일 가능성이 높다.
=== 파드 어피니티와 안티-어피니티를 이용해 파드 함께 배치하기 ===
* p699
* 쿠버네티스가 프론트엔드 파드와 백엔드 파드를 서로 가깝게 유지하면서 적절한 곳에 배포하도록 하는 게 낫다. 이는 파드 어피니티를 사용해 달성할 수 있다.
*
* p700
{{{
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: frontend
spec:
replicas: 5
template:
metadata:
labels:
app: frontend
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- topologyKey: kubernetes.io/hostname
labelSelector:
matchLabels:
app: frontend
}}}
* 예제는 이 디플로이먼트에서 app=backend 레이블이 있는 파드와 동일한 노드/topology에 배포되도록 하는 필수 요구 사항을 갖는 파드를 생성하는 것을 보여준다.
* 백엔드 파드를 스케줄링 하는 과정에서 파드 간의 어피니티로 인해 node2가 node1보다 높은 점수를 받았다는 것을 알 수 있다.
* p703
* 노드 선호도를 지정해 스케줄러가 특정 노드에 파드를 스케줄링하도록 지시하되 해당 노드가 어떤 이유로든 파드에 맞지 않을 경우 다른 곳으로 스케줄링되게 할 수 있다.
*{{{
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: frontend
spec:
replicas: 5
template:
metadata:
labels:
app: frontend
spec:
affinity:
podAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 80
podAffinityTerm:
topologyKey: kubernetes.io/hostname
labelSelector:
matchLabels:
app: backend
}}}
* p707
* 파드를 서로 멀리 떨어뜨려 놓고 싶을 수 있다. 이것을 파드 안티어피니티 podAntiAffinity 라고 한다.
* 두개의 파드 세트가 동일한 노드에서 실행되는 경우 서로의 성능을 방해하는 경우 이 기능을 사용한다.
*{{{
piVersion: extensions/v1beta1
kind: Deployment
metadata:
name: frontend
spec:
replicas: 5
template:
metadata:
labels:
app: frontend
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- topologyKey: kubernetes.io/hostname
labelSelector:
matchLabels:
app: frontend
...
}}}
== 애플리케이션 개발을 위한 모범 사례 ==== 쿠버네티스의 확장 ==
Contents
- 1. 쿠버네티스 소개
- 2. 도커와 쿠버네티스 첫걸음
- 3. 파드: 쿠버네티스에서 컨테이너 실행
- 4. 레플리케이션과 그 밖의 컨트롤러: 관리되는 파드 배포
- 5. 서비스: 클라이언트가 파드를 검색하고 통신을 가능하게 함
- 6. 볼륨: 컨테이너에 디스크 스토리지 연결
- 7. 컨피그맵과 시크릿: 애플리케이션 설정
- 8. 애플리케이션에서 파드 메타데이터와 그 외의 리소스에 액세스하기
- 9. 디플로에먼트: 선언적 애플리케이션 업데이트
- 10. 스테이트풀셋: 복제된 스테이트풀 애플리케이션 배포하기
- 11. 쿠버네티스 내부 이해
- 12. 쿠버네티스 API 서버 보안
- 13. 클러스터 노드와 네트워크 보안
- 14. 파드의 컴퓨팅 리소스 관리
- 15. 파드와 클러스터 노드의 오토스케일링
- 16. 고급 스케줄링
- 17. 애플리케이션 개발을 위한 모범 사례
- 18. 쿠버네티스의 확장
1. 쿠버네티스 소개 ¶
* p37
* p39
- 몇 년 전만 하더라도 대부분의 소프트웨어 어플리케이션은 하나의 프로세스 또는 몇 개의 서버에분산된 프로세스로 실행되는 거대한 모놀리스(monolith)였다.
* p39
- 쿠버네티스는 하드웨어 인프라를 추상화하고 데이터 센터 전체를 하나의 거대한 컴퓨팅 리소스로 제공한다
- 모놀리스 어플리케이션의 일부분이 수평적으로 확장하기 매우 어렵거나 불가능하고, 어떻게든 분할할 수 없다면 전체 어플리케이션을 확장할 수 없다.
- 마이크로서비스는 일반적으로 RESTFul API를 제공하는 HTTP와 같은 동기 프로토콜과 AMQP와 같은 비동기 프로토콜로 통신한다.
- 각 마이크로서비스는 대체로 정적인 외부 API를 제공하는 독립형 프로세스이기 때문에 개별적으로 개발, 배포할 수 있다.
- 시스템 관리자가 최신 보안 패치를 사용해 시스템을 최신 상태로 유지하는 데 주안점을 두는 데 반해, 많은 개발자는 그렇지 않다는 점이 두 시스템 간의 큰 차이를 만들게 된다.
- 우리 회사에서는 개발자들 간에 보수와 진보로 나뉘어져 싸우는걸 보느라면은... 암호나 일단 제대로 걸라고요 - 김준석
- 우리 회사에서는 개발자들 간에 보수와 진보로 나뉘어져 싸우는걸 보느라면은... 암호나 일단 제대로 걸라고요 - 김준석
- 개발자가 프로덕션 환경에서 애플리케이션을 실행하는 데 더 많이 관여하게 되면, 사용자가 무엇을 필요로 하고 어떤 문제가 있는지, 운영 팀이 애플리케이션을 유지하면서 직면하는 문제가 무엇인지 더 잘 이해할 수 있다.
- 하드웨어 인프라를 전혀 알지 못하더라도 운영 팀을 거치지 않고 개발자가 애플리케이션을 직접 배포하는 방식이 가장 이상적이다. 이를 노옵스(NoOPs)라고 한다.
- 이건 또 뭐여 - 서지혜
- 이건 또 뭐여 - 서지혜
- 가상머신을 사용해 각 마이크로서비스의 환경을 격리하는 대신 개발자들은 리눅스 컨테이너 기술로 눈을 돌렸다.
- 컨테이너에서 실행되는 프로세스는 다른 모든 프로세스와 마찬가지로 호스트 운영체제 내에서 실행된다. 그러나 컨테이너의 프로세스는 여전히 다른 프로세스와 격리돼 있다.
- 가상머신과 컨테이너의 차이가 뭐지?! - 서지혜
- 가상머신과 컨테이너의 차이가 뭐지?! - 서지혜
- 컨테이너를 가상머신과 비교하면 컨테이너는 훨씬 더 가벼워서 동일한 하드웨어에서 더 많은 수의 소프트웨어 구성 요소를 실행할 수 있다. 가상머신은 구성 요소 프로세스뿐만 아니라 시스템 프로세스를 실행해야 하기 때문에 추가 컴퓨팅 리소스가 필요하다.
- 컨테이너는 호스트 OS에서 실행되는 동일한 커널에서 시스템 콜을 수행한다.
- 가상머신은 게스트OS가 하이퍼바이저로 추상화된 호스트OS를 사용하지만 컨테이너는 호스트OS를 직접 사용하기 때문에 더 가벼운 거구나 - 서지혜
- 가상머신은 게스트OS가 하이퍼바이저로 추상화된 호스트OS를 사용하지만 컨테이너는 호스트OS를 직접 사용하기 때문에 더 가벼운 거구나 - 서지혜
- 이 커널은 호스트의 CPU 에서 x86의 명령을 수행하는 유일한 커널이다.
- 컨테이너 격리를 가능하게 하는 메커니즘 소개
- 두 가지 메커니즘으로 가능하다.
- 첫 번째는 리눅스 네임스페이스(namespace)로 각 프로세스가 시스템에 대한 독립된 뷰만 볼 수 있도록 한다. 두 번째는 리눅스 컨트롤 그룹(cgroups)으로, 프로세스가 사용할 수 있는 리소스의 양을 제한한다.
- 컨테이너 기술은 오랫동안 사용돼 왔지만 도커 컨테이너 플랫폼의 등장으로 더 널리 알려지게 됐다.
- Linux 컨테이너 기술은 2006년부터 연구되어왔고, 도커 초창기 라이브러리는 리눅스컨테이너 라이브러리를 참고하고있었다. 하지만 요즘은 linux 컨테이너에서 제공되지 않는 기능과 버전 종속성을 벗어나기 위해 독자적 라이브러리를 구축함 - 김준석
- Linux 컨테이너 기술은 2006년부터 연구되어왔고, 도커 초창기 라이브러리는 리눅스컨테이너 라이브러리를 참고하고있었다. 하지만 요즘은 linux 컨테이너에서 제공되지 않는 기능과 버전 종속성을 벗어나기 위해 독자적 라이브러리를 구축함 - 김준석
- 컨테이너의 프로세스가 기본 레이어 중 하나에 있는 파일에 쓰면 전체 파일의 복사본의 최상위 레이어에 만들어지고 프로세스는 복사본에 쓴다.
- 현재는 overlayFS2를 쓰고있는것으로 앎. 당근 버전업은 overlayFS에 스펙을 추가한거고 도커 버전이 업되면 신경쓸일 없음. - 김준석
- 현재는 overlayFS2를 쓰고있는것으로 앎. 당근 버전업은 overlayFS에 스펙을 추가한거고 도커 버전이 업되면 신경쓸일 없음. - 김준석
- 머신이 다른 버전의 리눅스 커널로 실행되거나 동일한 커널 모듈을 사용할 수 없는 경우 어플리케이션이 실행 될 수 없다.
- 다른 커널 버전 OS에서 컨테이너가 전혀 돌아가지 않는다는 소리를 좀 해야할것 같은데. Linux Standard Base(LSB)로 ISO 표준 시스템 콜 API은 호환이 되어서 되긴할껀데.. 아마 minimum kernel 버전을 요구하는데도 있을거고.. https://en.wikipedia.org/wiki/Linux_Standard_Base - 김준석
- 다른 커널 버전 OS에서 컨테이너가 전혀 돌아가지 않는다는 소리를 좀 해야할것 같은데. Linux Standard Base(LSB)로 ISO 표준 시스템 콜 API은 호환이 되어서 되긴할껀데.. 아마 minimum kernel 버전을 요구하는데도 있을거고.. https://en.wikipedia.org/wiki/Linux_Standard_Base - 김준석
- 구글은 10년동안 보그와 오메가를 비밀로 유지하다가 2014년 보그, 오메가, 기타 내부 구글 시스템으로 얻은 경험을 기반으로 하는 오픈소스 시스템인 쿠버네티스를 출시했다.
- 구글이 Hadoop으로 배운게 컸나보네 - 서지혜
- 구글이 Hadoop으로 배운게 컸나보네 - 서지혜
- 서비스 디스커버리, 스케일링, 로드밸런싱, 자가 치유, 리더 선출 같은 것들이 포함된다.
- 리더 선출은 처음 들어보네 https://en.wikipedia.org/wiki/Leader_election 이거 zookeeper가 사용한다고 되어있는데 안써봄, 69P에 방법이 나와있네 - 김준석
- Active stanby방식의 좀더 자동화되고 복잡한 버전 쯤 되는것 같아요 - bluemir
- Active stanby방식의 좀더 자동화되고 복잡한 버전 쯤 되는것 같아요 - bluemir
- 리더 선출은 처음 들어보네 https://en.wikipedia.org/wiki/Leader_election 이거 zookeeper가 사용한다고 되어있는데 안써봄, 69P에 방법이 나와있네 - 김준석
- 마스터 노드는 전체 쿠버네이트 시스템을 제어하고 관리하는 쿠버네티스 컨트롤 플레인을 실행한다. 워커 노드는 실제 배포되는 컨테이너 애플리케이션을 실행한다
- 마스터-워커 구성은 클러스터 시스템들의 기본 아키텍쳐로구만 - 서지혜
- 마스터-워커 구성은 클러스터 시스템들의 기본 아키텍쳐로구만 - 서지혜
- 저자는 (...) 동작 방식부터 설명하는 방식을 싫어한다.
- kube-proxy는 서비스를 제공하는 모든 컨테이너에서 서비스 연결이 로드밸런싱되도록 한다.
- 인프라에 장애가 발생한 노드가 없어도 정상적인 시스템 작동이 가능하도록 충분한 예비 자원이 있는 경우 운영 팀은 새벽 3시에 일어난 장애에 즉시 대응할 필요가 없다.
- 동남아가 제발 하드좀 잘 관리해줬으면.. 예비 자원좀 - 김준석
- 요건 트루입니다. 이러저런 운영 자동화를 통해서 95% 이상의 이벤트는 자동 처리할수 있고, 나머지는 다음날 봐도 될정도...
- 동남아가 제발 하드좀 잘 관리해줬으면.. 예비 자원좀 - 김준석
2.1. 도커를 사용한 컨테이너 이미지 생성, 실행, 공유하기 ¶
- p73
- busybox( https://en.wikipedia.org/wiki/BusyBox)는 echo, ls, gzip 등과 같은 표준 UNIX 명령줄 도구들을 합쳐 놓은 단일 실행파일(executable)이라 할 수 있다.
- busybox는 ubuntu 부팅할때 접해볼수 있는데 개별 명령어 대신 busybox로 대체한다. 부팅디스크를 이용한 OS 구동때는 ram에 공간을 만드는데, 빡빡하게 용량을 관리하기 때문에 busybox를 쓴다. - 김준석
- busybox는 ubuntu 부팅할때 접해볼수 있는데 개별 명령어 대신 busybox로 대체한다. 부팅디스크를 이용한 OS 구동때는 ram에 공간을 만드는데, 빡빡하게 용량을 관리하기 때문에 busybox를 쓴다. - 김준석
- busybox( https://en.wikipedia.org/wiki/BusyBox)는 echo, ls, gzip 등과 같은 표준 UNIX 명령줄 도구들을 합쳐 놓은 단일 실행파일(executable)이라 할 수 있다.
- p76
FROM node:7 ADD app.js /app.js ENTRYPOINT ["node", "app.js"]
- Dockerfile을 쓴지 오래되긴 했다. - 김준석
- p79
- 이미지라는 것이 하나의 큰 바이너리 덩어리가 아니라 여러개의 레이어로 구성된다는 것을 아마도 눈치챘을 것이다. 서로 다른 이미지가 여러 개의 레이어를 공유할 수 있기 때문에 이미지의 저장과 전송에 효과적이다.
- 기본 이미지를 구성하는 모든 레이어는 단 한 번만 저장될 것이다. 또한 이미지를 가져올 때도 도커는 각 레이어를 개별적으로 다운로드 한다. 컴퓨터에 여러개의 레이어가 이미 저장돼 있다면 도커는 저장되지 않은 레이어만 다운로드 한다.
- 이미지라는 것이 하나의 큰 바이너리 덩어리가 아니라 여러개의 레이어로 구성된다는 것을 아마도 눈치챘을 것이다. 서로 다른 이미지가 여러 개의 레이어를 공유할 수 있기 때문에 이미지의 저장과 전송에 효과적이다.
- p80
- p82
$ docker exec -it kubia-container bash
2.2. 쿠버네티스 클러스터 설치 ¶
2.3. 쿠버네티스에 첫 번째 애플리케이션 실행하기 ¶
- p97
- p98
- ` kubectl get pods `
- kgp - 김준석
- kgp - 김준석
- ` kubectl get pods `
- p99
- kubectl 명령어를 실행하면 쿠버네티스의 API 서버로 REST HTTP 요청을 전달하고 클러스터에 새로운 레플리케이션컨트롤러 오브젝트를 생성한다.
- 클라이언트 -> 서버 -> 명령 수행 - 김준석
- 클라이언트 -> 서버 -> 명령 수행 - 김준석
- kubectl 명령어를 실행하면 쿠버네티스의 API 서버로 REST HTTP 요청을 전달하고 클러스터에 새로운 레플리케이션컨트롤러 오브젝트를 생성한다.
- p100
- p101
- ` kubectl expose rc kubia --type= LoadBalancer --name kubia-http `
- ` kubernetes 서비스에 관한 설명은 생략 `
- ` kubectl expose rc kubia --type= LoadBalancer --name kubia-http `
- p103
- kubectl run 명령을 수행하면 레플리케이션컨트롤러를 생성하고 레플리케이션컨트롤러가 실제 파드를 생성한다.
- 띄어쓰기 좀.. - 서지혜
- 띄어쓰기 좀.. - 서지혜
- 마스터 노드가 단일 마스터 노드에서 호스팅 중인지 혹은 여러 대의 마스터 노드에 분산된 것인지 알 수 없다.
- kubectl run 명령을 수행하면 레플리케이션컨트롤러를 생성하고 레플리케이션컨트롤러가 실제 파드를 생성한다.
- p104
- 레플리케이션컨트롤러는 사라진 파드를 대체하기 위해 새로운 파드를 생성할 것이다.
- 파드는 일시적(ephermeral)이다.
- 새로운 파드는 다른 IP 주소를 할당받는다. 이것이 바로 서비스가 필요한 이유다.
- 레플리케이션컨트롤러는 사라진 파드를 대체하기 위해 새로운 파드를 생성할 것이다.
- p106
- ` kubectl scale rc kubia --replicas=3 `
- ` kubectl get rc `
- ` kubectl scale rc kubia --replicas=3 `
- p107
- 서비스는 다수 파드 앞에서 로드밸런서 역할을 한다. 파드가 하나만 있으면 서비스는 이 파드 하나에 정적 주소를 제공한다.
- 서비스는 다수 파드 앞에서 로드밸런서 역할을 한다. 파드가 하나만 있으면 서비스는 이 파드 하나에 정적 주소를 제공한다.
- p109
- 어떤 노드에 파드가 스케줄링됐는지 궁금할 수 있다. 쿠버네티스에서는 파드가 적절히 실행하는 데 필요한 CPU와 메모리를 제공하는 노드에 스케줄링됐다면, 어떤 노드에 파드가 실행 중인지는 중요하지 않다.
- 파드를 조회할 때 파드 IP와 실행 중인 노드 표시하기
- {{ $ kubectl get pods -o wide }}}
- 어떤 노드에 파드가 스케줄링됐는지 궁금할 수 있다. 쿠버네티스에서는 파드가 적절히 실행하는 데 필요한 CPU와 메모리를 제공하는 노드에 스케줄링됐다면, 어떤 노드에 파드가 실행 중인지는 중요하지 않다.
- p110
- 쿠버네티스 또한 꽤 멋진 웹 대시보드를 함께 제공한다는 점을 알게 되면 기뻐할 것이다.
- 실제로 하드하게 써보면 별로 안기쁘더라구요 - bluemir
- 실제로 하드하게 써보면 별로 안기쁘더라구요 - bluemir
- 쿠버네티스 또한 꽤 멋진 웹 대시보드를 함께 제공한다는 점을 알게 되면 기뻐할 것이다.
3.1. 파드 소개 ¶
- p114
- 파드는 함께 배치된 컨테이너 그룹이며 쿠버네티스의 기본 빌딩 블록이다.
- 모든 컨테이너는 항상 하나의 워커 노드에서 실행되며 여러 워커 노드에 걸쳐 실행되지 않는다.
- 궁금했던 부분. 리소스를 테트리스는 어려운거군 - 서지혜
- 궁금했던 부분. 리소스를 테트리스는 어려운거군 - 서지혜
- IPC 혹은 로컬 파일을 통해 통신하는 여러 프로세스로 구성돼, 같은 노드에서 실행해야 하는 애플리케이션을 상상해보자.
- 모든 프로세스는 동일한 표준 출력으로 로그를 기록하기 때문에 어떤 프로세스가 남긴 로그인지 파악하는 것이 매우 어렵다.
- 파드는 함께 배치된 컨테이너 그룹이며 쿠버네티스의 기본 빌딩 블록이다.
- p116
- UTC 네임스페이스
- 비슷하게 파드의 모든 컨테이너는 동일한 IPC 네임스페이스 아래에서 실행되 IPC를 통해 서로 통신할 수 있다.
- 플랫한 공유 네트워크 주소 공간에 상주하므로 모든 파드는 다른 파드의 IP주소를 사용해 접근하는 것이 가능하다.
- UTC 네임스페이스
- p117
- 파드 사이에서 통신은 항상 단순하다. 두 파드가 동일 혹은 서로 다른 워커 노드에 있는지는 중요하지 않으며, 두 경우 모두 파드 안에 있는 컨테이너는 NAT 없는 플랫 네트워크를 통해 서로 통신하는 것이 가능하다,
- 이것은 실제 노드 간 네트워크 토폴로지와 관계없이, 근거리 네트워크에 있는 컴퓨터 간의 통신과 비슷하다.
- 파드는 논리적인 호스트로서 컨테이너가 아닌 환경에서의 물리적 호스트 혹은 VM과 매우 유사하게 동작한다.
- 파드 사이에서 통신은 항상 단순하다. 두 파드가 동일 혹은 서로 다른 워커 노드에 있는지는 중요하지 않으며, 두 경우 모두 파드 안에 있는 컨테이너는 NAT 없는 플랫 네트워크를 통해 서로 통신하는 것이 가능하다,
- p118
- p119
- 프론트엔드 구성 요소는 백엔드와 완전히 다른 스케일링 요구 사항을 갖고있어 개별적으로 확장하는 경향이 있다.
- 사이트카 컨테이너의 다른 예제로는 로그 로테이터와 수집기, 데이터 프로세서, 통신 어댑터 등이 있다.
- 프론트엔드 구성 요소는 백엔드와 완전히 다른 스케일링 요구 사항을 갖고있어 개별적으로 확장하는 경향이 있다.
3.2. YAML또는 JSON 디스크립터로 파드 생성 ¶
- p121
$ kubectl get po kubia-zxzij -o yaml
- pod의 약자... - 서지혜
- pod의 약자... - 서지혜
- p123
- 거의 모든 쿠버네티스 리소스가 갖고 있는 세 가지 중요한 부분이 있다. Metadata, spec, status
- Metadata: 이름, 네임스페이스, 레이블 및 파드에 관한 기타 정보를 포함한다.
- Spec: 파드 컨테이너, 볼륨, 기타 데이터 등 파드 자체에 관한 실제 명세를 가진다.
- Status: 파드 상태, 각 컨테이너 설명과 상태, 파드 내부 IP, 기타 기본 정보 등 현재 실행 중인 파드에 관한 현재 정보를 포함한다.
- 거의 모든 쿠버네티스 리소스가 갖고 있는 세 가지 중요한 부분이 있다. Metadata, spec, status
- p125
kubectl explain
- p126
$ kubectl create -f kubia-manual.yaml
- p128
$ kubectl logs kubia-manual -c kubia
3.3. 레이블을 이용한 파드 구성 ¶
- p130
- 파드 수가 증가함에 따라 파드를 부분 집합으로 분류할 필요가 있다.
- 파드 수가 증가함에 따라 파드를 부분 집합으로 분류할 필요가 있다.
- p131
- 레이블은 리소스에 첨부하는 키-값 쌍으로, 이 쌍은 레이블 셀렉터를 사용해 리소스를 선택할 때 활용된다.
- 레이블은 리소스에 첨부하는 키-값 쌍으로, 이 쌍은 레이블 셀렉터를 사용해 리소스를 선택할 때 활용된다.
- p133
- kubectl get pods 명령은 레이블을 표시하지 않는 것이 기본값이라 --show-labels 스위치를 사용해 레이블을 볼 수 있다.
- 모든 레이블을 나영하는 대신 특정 레이블에만 관심 있는 경우 해당 레이블을 -L 스위치로 지정해 각 레이블을 자체 열에 표시할 수 있다.
- kubectl get pods 명령은 레이블을 표시하지 않는 것이 기본값이라 --show-labels 스위치를 사용해 레이블을 볼 수 있다.
3.4. 레이블 셀렉터를 이용해 파드 부분 집합 나열 ¶
- p135
$ kubectl get po -l creation_method=manual
$ kubectl get po -l '!env'
- p137
- 레이블 셀렉터는 파드 목록을 나열하는 것뿐만 아니라, 파드 부분 집합에 작업을 수행할 때도 유용하다.
- 레이블 셀렉터는 파드 목록을 나열하는 것뿐만 아니라, 파드 부분 집합에 작업을 수행할 때도 유용하다.
- p139
- 쿠버네티스의 전체적인 아이디어는 그 위에 실행되는 애플리케이션으로부터 실제 인프라스트럭처를 숨기는 것에 있기에 파드가 어떤 노드에 스케줄링 돼야 하는지 구체적으로 지정하고 싶지는 않은 것이다. 그로 인해 애플리케이션이 인프라스트럭처에 결합되기 때문이다. 그러나 정확한 노드를 지정하는 대신 필요한 노드 요구 사항을 기술하고 쿠버네티스가 요구 사항을 만족하는 노드를 선택하도록 한다. 이는 노드 레이블과 레이블 셀렉터를 통해 할 수 있다.
- 노드를 포함한 모든 쿠버네티스 오브젝트에 레이블을 부착할 수 있다.
- 쿠버네티스의 전체적인 아이디어는 그 위에 실행되는 애플리케이션으로부터 실제 인프라스트럭처를 숨기는 것에 있기에 파드가 어떤 노드에 스케줄링 돼야 하는지 구체적으로 지정하고 싶지는 않은 것이다. 그로 인해 애플리케이션이 인프라스트럭처에 결합되기 때문이다. 그러나 정확한 노드를 지정하는 대신 필요한 노드 요구 사항을 기술하고 쿠버네티스가 요구 사항을 만족하는 노드를 선택하도록 한다. 이는 노드 레이블과 레이블 셀렉터를 통해 할 수 있다.
3.6. 네임스페이스를 사용한 리소스 그룹화 ¶
- p143
- 여러 네임스페이스를 사용하면 많은 구성 요소를 가진 복잡한 시스템을 좀 더 작은 개별 그룹으로 분리할 수 있다. 또한 멀티테넌트 환경처럼 리소스를 분리하는 데 사용된다.
- 리소스 이름은 네임스페이스 안에서만 고유하면 된다.
- 여러 네임스페이스를 사용하면 많은 구성 요소를 가진 복잡한 시스템을 좀 더 작은 개별 그룹으로 분리할 수 있다. 또한 멀티테넌트 환경처럼 리소스를 분리하는 데 사용된다.
- p145
- 네임스페이스를 사용해 서로 관계없는 리소스를 겹치지 않는 그룹으로 분리할 수 있다.
- 네임스페이스를 사용해 서로 관계없는 리소스를 겹치지 않는 그룹으로 분리할 수 있다.
3.7. 파드 중지와 제거 ¶
- p148
- 쿠버네티스는 SIGTERM 신호를 프로세스에 보내고 지정된 시간(기본값 30초) 동안 기다린다. 시간 내에 종료되지 않으면 SIGKILL 신호를 통해 종료한다. 프로세스가 항상 정상적으로 종료되게 하기 위해서는 SIGTERM 신호를 올바르게 처리해야 한다.
- 쿠버네티스는 SIGTERM 신호를 프로세스에 보내고 지정된 시간(기본값 30초) 동안 기다린다. 시간 내에 종료되지 않으면 SIGKILL 신호를 통해 종료한다. 프로세스가 항상 정상적으로 종료되게 하기 위해서는 SIGTERM 신호를 올바르게 처리해야 한다.
- p151
$ kubectl delete all -all
4.1. 파드를 안정적으로 유지하기 ¶
4.2. 레플리케이션컨트롤러 소개 ¶
- p154
- p155
- 애플리케이션이 더 이상 제대로 동작하지 않는다는 신호를 쿠버네티스에 보내서, 쿠버네이트가 애플리케이션을 다시 시작하도록 하는 방법이 있다면 좋을 것이다.
- 그래서 라이브니스 프로브 설정을 해야하는군 - 서지혜
- 그래서 라이브니스 프로브 설정을 해야하는군 - 서지혜
- 쿠버네티스는 라이브니스 프로브를 통해 컨테이너가 살아 있는지 확인할 수 있다.
- 쿠버네티스는 세 가지 메커니즘을 사용해 컨테이너에 프로브를 실행한다.
- HTTP GET 프로브는 지정한 IP 주소, 포트, 경로에 HTTP GET 요청을 수행한다. ... 응답 코드가 오류를 나타내지 않는 경우에 프로브가 성공했다고 간주된다.
- TCP 소켓 프로브는 컨테이너의 지정된 포트에 TCP 연결을 시도한다. 연결에 성공하면 프로브가 성공한 것
- TCP는 응답까지는 보지 않는구나 - 서지혜
- TCP는 응답까지는 보지 않는구나 - 서지혜
- Exec 프로브는 컨테이너 내의 임의의 명령을 실행하고 명령의 종료 상태 코드를 확인한다. 상태 코드가 0이면 프로브가 성공한 것이다.
- HTTP GET 프로브는 지정한 IP 주소, 포트, 경로에 HTTP GET 요청을 수행한다. ... 응답 코드가 오류를 나타내지 않는 경우에 프로브가 성공했다고 간주된다.
- 애플리케이션이 더 이상 제대로 동작하지 않는다는 신호를 쿠버네티스에 보내서, 쿠버네이트가 애플리케이션을 다시 시작하도록 하는 방법이 있다면 좋을 것이다.
- p158
- 크래시된 컨테이너의 애플리케이션 로그 얻기
$ kubectl logs mypod --previous
- 크래시된 컨테이너의 애플리케이션 로그 얻기
- p159
- 숫자 137은 두 숫자를 합한 값으로, 128 + x다. ...이 예에서 x는 SIGKILL 시그널 번호인 9이며, 프로세스가 강제로 종료됐음을 의미한다.
- 숫자 137은 두 숫자를 합한 값으로, 128 + x다. ...이 예에서 x는 SIGKILL 시그널 번호인 9이며, 프로세스가 강제로 종료됐음을 의미한다.
- p162
- p164
- 레플리케이션컨트롤러는 실행 중인 파드 목록을 지속적으로 모니터링하고, 특정 "유형"의 실제 파드 수가 의도하는 수와 일치하는지 항상 확인한다.
- 레플리케이션컨트롤러는 파드 유형이 아니라 특정 레이블 셀렉터와 일치하는 파드 세트에 작동한다.
- 레플리케이션컨트롤러는 실행 중인 파드 목록을 지속적으로 모니터링하고, 특정 "유형"의 실제 파드 수가 의도하는 수와 일치하는지 항상 확인한다.
- p165
- 레플리케이션컨트롤러에는 세 가지 필수 요소가 있다. 레이블 셀렉터 / 레플리카 수 / 파드 템플릿
- https://kubernetes.io/ko/docs/concepts/workloads/controllers/deployment/ 디플로에먼트를 주로 봐서 RC와 헷갈림. 디플로이먼트(Deployment) 는 파드와 레플리카셋( ReplicaSet)에 대한 선언적 업데이트를 제공한다. 이렇게 보면 deploy가 나와야할것 같은데? - 김준석
- https://kubernetes.io/ko/docs/concepts/workloads/controllers/replicationcontroller 에서 ReplicaSet을 구성하는 Deployment가 권장하는 방법이라고 하네요 - 서지혜
- https://kubernetes.io/ko/docs/concepts/workloads/controllers/deployment/ 디플로에먼트를 주로 봐서 RC와 헷갈림. 디플로이먼트(Deployment) 는 파드와 레플리카셋( ReplicaSet)에 대한 선언적 업데이트를 제공한다. 이렇게 보면 deploy가 나와야할것 같은데? - 김준석
- 레플리케이션컨트롤러에는 세 가지 필수 요소가 있다. 레이블 셀렉터 / 레플리카 수 / 파드 템플릿
- p166
- p172
- p173
- p175
$ kubectl label pod kubia-dmdck app=foo --overwrite
- 치트 시트 - 김준석
- 치트 시트 - 김준석
- p177
- p179
4.3. 레플리케이션컨트롤러 대신 레플리카셋 사용하기 ¶
- p183
- p185
- p186
- p188
- 레플리카셋을 삭제하면 모든 파드가 삭제된다.
- 레플리카셋은 cascade=false 옵션 없나? - 서지혜
- 레플리카셋은 cascade=false 옵션 없나? - 서지혜
- 레플리카셋을 삭제하면 모든 파드가 삭제된다.
4.4. 데몬셋을 사용해 각 노드에서 정확히 한개의 파드 실행하기 ¶
- p188
- p189
- 데몬셋은 그림 4.8과 노드 수만큼 파드를 만들고 각 노드에 배포된다.
- 새 노드가 클러스터에 추가되면 데몬셋은 즉시 새 파드 인스턴스를 새 노드에 배포한다.
- 정의 밑줄 - 김준석
- 정의 밑줄 - 김준석
- 데몬셋 정의의 일부인 파드 템플릿에서 node-selector 속성을 지정하면된다.
- 데몬셋은 그림 4.8과 노드 수만큼 파드를 만들고 각 노드에 배포된다.
- p192
4.5. 완료 가능한 단일 태스크를 수행하는 파드 실행 ¶
- p194
- p196
- 잡 파드는 무한정 실행하지 않으므로 기본 정책을 사용할 수 없다. 따라서 restartPolicy를 onFailure나 Never로 명시적으로 설정해야 한다.
- 유의사항 밑줄 - 김준석
- 유의사항 밑줄 - 김준석
- 잡 파드는 무한정 실행하지 않으므로 기본 정책을 사용할 수 없다. 따라서 restartPolicy를 onFailure나 Never로 명시적으로 설정해야 한다.
- p197
4.6. 잡을 주기적으로 또는 한 번 실행되도록 스케줄링하기 ¶
- p200
- 리눅스나 유닉스 같은 운영체제에서 이런 작업을 크론 작업이라 한다. 쿠버네티스에서도 이를 지원한다.
- 다들 아는 그 cron - 김준석
- 다들 아는 그 cron - 김준석
- 리눅스나 유닉스 같은 운영체제에서 이런 작업을 크론 작업이라 한다. 쿠버네티스에서도 이를 지원한다.
- p201
- 스케줄 설정하기
- 일반적인 상황에서 크론잡은 스케줄에 설정한 각 실행에 항상 하나의 잡만 생성하지만 두 개의 잡이 동시에 생성되거나 전혀 생성되지 않을 수 있다.
- 스케줄 설정하기
5.1. 서비스 소개 ¶
- p206
- 쿠버네티스의 서비스는 동일한 서비스를 제공하는 파드 그룹에 지속적인 단일 접점을 만들려고 할 때 생성하는 리소스다. 각 서비스는 서비스가 존재하는 동안 절대 바뀌지 않는 IP주소와 포트가 있다. 클라이언트는 해당 IP와 포트로 접속한 다음 해당 서비스를 지원하는 파드 중 하나로 연결된다.
- 정의 밑줄 - 김준석
- 정의 밑줄 - 김준석
- 쿠버네티스의 서비스는 동일한 서비스를 제공하는 파드 그룹에 지속적인 단일 접점을 만들려고 할 때 생성하는 리소스다. 각 서비스는 서비스가 존재하는 동안 절대 바뀌지 않는 IP주소와 포트가 있다. 클라이언트는 해당 IP와 포트로 접속한 다음 해당 서비스를 지원하는 파드 중 하나로 연결된다.
- p208
- 서비스 연결은 서비스 뒷단의 모든 파드로 로드밸런싱된다. 레이블셀렉터를 기억할 것이다.
- 동작 밑줄 - 김준석
- 동작 밑줄 - 김준석
- 서비스 연결은 서비스 뒷단의 모든 파드로 로드밸런싱된다. 레이블셀렉터를 기억할 것이다.
- p210
- 서비스의 클러스터 IP로 요청을 보내고 응답을 로그로 남기는 파드를 만드는 것이다.
- 쿠버네티스 노드로 ssh 접속하고 curl 명령을 실행할 수 있따.
- kubectl exec 명령어로 기존 파드에서 curl 명령을 실행할 수 있다.
- 위 세개다 쓰는듯. 파드에서 curl을 하는것은 번거로워서 가장 늦게 하긴 함. - 김준석
- 위 세개다 쓰는듯. 파드에서 curl을 하는것은 번거로워서 가장 늦게 하긴 함. - 김준석
- 서비스의 클러스터 IP로 요청을 보내고 응답을 로그로 남기는 파드를 만드는 것이다.
- p211
- 명령어의 더블 대시(--)는 kubectl 명령줄 옵션의 끝을 의미한다.
- 번역이 이상한데 공식 홈페이지의
Note: The double dash (--) separates the arguments you want to pass to the command from the kubectl arguments.
kubectl 에서 넘기고싶은걸 -- 로 구분할수 있다는 거임. - 김준석
- 번역이 이상한데 공식 홈페이지의
- 명령어의 더블 대시(--)는 kubectl 명령줄 옵션의 끝을 의미한다.
- p212
- p213
- 여러 포트가 있는 서비스를 만들 때는 각 포트의이름을 지정해야 한다.
- 정의 밑줄 - 김준석
- 정의 밑줄 - 김준석
- 여러 포트가 있는 서비스를 만들 때는 각 포트의이름을 지정해야 한다.
- p216
$ kubectl exec kubia-3inly env
- KUBERNETES_SERVICE_HOST 와 KUBERNETEST_SERVICE_PORT 가 있는걸 첨알았네 - 김준석
- KUBERNETES_SERVICE_HOST 와 KUBERNETEST_SERVICE_PORT 가 있는걸 첨알았네 - 김준석
- p217
5.3. 외부 클라이언트에 서비스 노출 ¶
5.4. 인그레스 리소스로 서비스 외부 노출 ¶
- p245
- 인그레이스는 비교적 새로운 쿠버네티스 기능이므로 향후 많은 개선과 새로운 기능를 기대할 수 있다.
- https://kubernetes.io/docs/reference/using-api/deprecation-guide/#ingress-v122 1.19까지 사용가능하고 deprecated됨? - 김준석
- istio 나 기타 다른 Ingress 발전속도가 워낙 빨라서 k8s Ingress spec을 update 속도가 못따라가서 그렇습니다. k8s Ingress Spec으로는 안되는기능이 너무 많아요. 지금 대세는 Istio를 쓰는 것입니다(Istio가 Ingress기능만 하는건 아닙니다.) - bluemir
- istio 나 기타 다른 Ingress 발전속도가 워낙 빨라서 k8s Ingress spec을 update 속도가 못따라가서 그렇습니다. k8s Ingress Spec으로는 안되는기능이 너무 많아요. 지금 대세는 Istio를 쓰는 것입니다(Istio가 Ingress기능만 하는건 아닙니다.) - bluemir
- https://kubernetes.io/docs/reference/using-api/deprecation-guide/#ingress-v122 1.19까지 사용가능하고 deprecated됨? - 김준석
- 인그레이스는 비교적 새로운 쿠버네티스 기능이므로 향후 많은 개선과 새로운 기능를 기대할 수 있다.
6.1. 볼륨 소개 ¶
- p260
- p263
- 볼륨을 채우거나 마운트하는 프로세스는 파드의 컨테이너가 시작되기 전에 수행된다.
- 다양한 유형의 볼륨이 사용 가능하다.
- emptyDir
- hostPath
- gitRepo
- nfs
- gcePersistentDisk, awsElasticBlockStore, azureDisk
- cinder, cephfs, iscsi, flocker, glusterfs, quobyte, rbd, flexVolume, csphereVolume, photonPersistentDisk, scaleIO
- configMap, secret, downwardAPI - 이것도 볼륨으로 치다니 김준석
- persistentVolumeClaim
- emptyDir
- 볼륨을 채우거나 마운트하는 프로세스는 파드의 컨테이너가 시작되기 전에 수행된다.
6.2. 볼륨을 사용한 컨테이너 간 데이터 공유 ¶
- p264
- emptyDir
- 이름에서 알 수 있듯이 볼륨이 빈 디렉터리로 시작된다.
- emptyDir 볼륨은 동일 파드에서 실행 중인 컨테이너 간 파일을 공유할 때 유용하다.
- 이름에서 알 수 있듯이 볼륨이 빈 디렉터리로 시작된다.
- emptyDir
- p268
- p269
- p271
- 사이트카 컨테이너 소개
- 새로운 로직을 메인 애플리케이션 코드에 밀어 넣어 복잡성을 더하고 재사용성을 떨어뜨리는 대신에 파드에 사이드카를 추가하면 기존 컨테이너 이미지를 사용할 수 있다.
- 이런거 좀 해설좀 자세히 해줬으면. 사이드카와 메인nginx사이 같은 공유공간을 가지고 있는데 사이드카 컨테이너가 gitRepo 볼륨을 가지고 주기적으로 밀어넣어서 웹페이지를 갱신한단 소리겠지? - 김준석
- 그것보단 log stash 같은 로그 수집기를 한 Container 내에 넣는 대신 별개의 Container 로 분리하면 나중에 Log 설정을 바꿔야 할떄 Application Container를 바꾸는대신 별개의 logstash sidecar를 바꾸면 된다는 의미입니다. 예시는 log 지만 Network관련 설정이나 Monitoring 설정등도 가능합니다. 또한 Cluster Provider 가 Sidecar inject를 제공하는 경우 Sidecar의 버전등이 Application 과는 완전 별개로 돌아 갈수 있으므로 Applicaiton 개발자와 Cluster Provider의 마찰도 줄일수 있습니다. 이런 구조를 가장 잘 활용하는것은 Istio(service mesh)가 있습니다.- bluemir
- 그것보단 log stash 같은 로그 수집기를 한 Container 내에 넣는 대신 별개의 Container 로 분리하면 나중에 Log 설정을 바꿔야 할떄 Application Container를 바꾸는대신 별개의 logstash sidecar를 바꾸면 된다는 의미입니다. 예시는 log 지만 Network관련 설정이나 Monitoring 설정등도 가능합니다. 또한 Cluster Provider 가 Sidecar inject를 제공하는 경우 Sidecar의 버전등이 Application 과는 완전 별개로 돌아 갈수 있으므로 Applicaiton 개발자와 Cluster Provider의 마찰도 줄일수 있습니다. 이런 구조를 가장 잘 활용하는것은 Istio(service mesh)가 있습니다.- bluemir
- 이런거 좀 해설좀 자세히 해줬으면. 사이드카와 메인nginx사이 같은 공유공간을 가지고 있는데 사이드카 컨테이너가 gitRepo 볼륨을 가지고 주기적으로 밀어넣어서 웹페이지를 갱신한단 소리겠지? - 김준석
- 사이트카 컨테이너 소개
- p272
- 프라이빗 깃 리포지터리를 컨테이너에 복제하려면.. 다른 유사 방법을 사용해야 한다
- 프라이빗 깃 리포지터리를 컨테이너에 복제하려면.. 다른 유사 방법을 사용해야 한다
6.3. 워커 노드 파일시스템의 파일 접근 ¶
- p273
- 파일시스템을 통해 노드 디바이스를 접근하기 위해 노드의 파일시스템을 사용해야 한다.
- 정의 밑줄 - 김준석
- 정의 밑줄 - 김준석
- hostPath 볼륨은 노드 파일시스템의 특정 파일이나 디렉터리를 가리킨다.
- 특정 노드에 역할(log보관, db)를 지정해서 하기때문에 우리쪽에선 자주 쓰인다 - 김준석
- 특정 노드에 역할(log보관, db)를 지정해서 하기때문에 우리쪽에선 자주 쓰인다 - 김준석
- hostPath 볼륨의 콘텐츠는 삭제되지 않는다.파드가 삭제되면 다음 파드가 호스트의 동일 경로를 가리키는 hostPath 볼륨을 사용하고, 이전 파드와 동일한 노드에 스케줄링된다는 조건에서 새로운 파드는 이전 파드가 남긴 모든 항목을 볼 수 있다.
- 하지만 노드에만 남기 때문에 노드간 공유는 안된다 - 서지혜
- 하지만 노드에만 남기 때문에 노드간 공유는 안된다 - 서지혜
- 볼륨의 콘텐츠는 특정 노드의 파일시스템에 저장되므로 데이터베이스 파드가 다른 노드로 다시 스케줄링되면 더 이상 이전 데이터를 볼 수 없다. hostPath 볼륨은 파드가 어떤 노드에 스케줄링되느냐에 따라 민감하기 때문에 일반적인 파드에 사용하는 것은 좋은 생각이 아니다.
- 파일시스템을 통해 노드 디바이스를 접근하기 위해 노드의 파일시스템을 사용해야 한다.
- p275
- 다른 파드를 살펴보면 대부분이 노드의 로그파일이나 kubeconfig, CA인증서를 접근하기 위해 이 유형의 볼륨을 사용한다는 것을 볼 수 있다.
- 그렇네 - 김준석
- 그렇네 - 김준석
- 다른 파드를 살펴보면 대부분이 노드의 로그파일이나 kubeconfig, CA인증서를 접근하기 위해 이 유형의 볼륨을 사용한다는 것을 볼 수 있다.
6.4. 퍼시스턴트 스토리지 사용 ¶
- p275
- p277
- p282
- 이런 유형의 인프라스트럭처 관련 정보를 파드 정의에 포함한다는 것은 파드 정의가 특정 쿠버네티스 클러스터에 밀접하게 연결됨을 의미한다.
- 개발자가 서버정보를 다 알아함 - 김준석
- 개발자가 서버정보를 다 알아함 - 김준석
- 이런 유형의 인프라스트럭처 관련 정보를 파드 정의에 포함한다는 것은 파드 정의가 특정 쿠버네티스 클러스터에 밀접하게 연결됨을 의미한다.
6.5. 기반 스토리지 기술과 파드 분리 ¶
- p283
- 이상적으로는 쿠버네티스에 애플리케이션을 배포하는 개발자는 기저에 어떤 종류의 스토리지 기술이 사용되는지 알 필요가 없어야 하고, 동일한 방식으로 파드를 실행하기 위해 어떤 유형의 물리 서버가 사용되는지 알 필요가 없어야 한다. 동일한 방식으로 파드를 실행하기 위해 어떤 유형의 물리 서버가 사용되는지 알 필요가 없어야 한다.
- 가상화때문에 난이도 +1 - 김준석
- 가상화때문에 난이도 +1 - 김준석
- 인프라스트럭처의 세부 사항을 처리하지 않고 애플리케이션이 쿠버네티스 클러스터에 스토리지를 요청할 수 있도록 하기 위해 새로운 리소스 두개가 도입됐다. 바로 퍼시스턴트 볼륨( PersistentVolume)과 퍼시스턴트볼륨클레임( PersistentVolumeClaim)이다.
- 클러스터 관리자가 퍼시스턴트볼륨을 프로비저닝하면 파드는 퍼시스턴트볼륨클레임을 통해 이를 사용한다.
- 클러스터 관리자는 네트워크 스토리지 유형을 설정한다.
- 관리자는 쿠버네티스 API에 PV 디스크립터를 게시해 퍼시스턴트볼륨을 생성한다.
- 사용자는 퍼시스턴트볼륨클레임을 생성한다.
- 쿠버네티스는 적정한 크기와 접근 모드의 PV를 찾고 PVC를 PV에 바인딩한다.
- 사용자는 PVC를 참조하는 볼륨을 가진 파드를 생성한다.
- 순서 밑줄 - 김준석
- 순서 밑줄 - 김준석
- 클러스터 관리자는 네트워크 스토리지 유형을 설정한다.
- 이상적으로는 쿠버네티스에 애플리케이션을 배포하는 개발자는 기저에 어떤 종류의 스토리지 기술이 사용되는지 알 필요가 없어야 하고, 동일한 방식으로 파드를 실행하기 위해 어떤 유형의 물리 서버가 사용되는지 알 필요가 없어야 한다. 동일한 방식으로 파드를 실행하기 위해 어떤 유형의 물리 서버가 사용되는지 알 필요가 없어야 한다.
- p285
kind: PersistentVolume metadata: name: mongodb-pv spec: capacity: storage: 1Gi accessModes: - ReadWriteOnce - ReadOnlymany persistentVolumeReclaimPolicy: Retain gcePersistentDisk : pdName: mongodb fsType: ext4
- 대략적인 yaml 밑줄 - 김준석
- p287
- p288
kind: PersistentVolumeClaim metadata: name: mongodb-pvc spec: resources: requests: storage: 1Gi accessModes: - ReadWriteOnce storageClassname: ""
- yaml 밑줄 - 김준석
- yaml 밑줄 - 김준석
kubectl get pvc
- p289
- 접근모드로 사용되는 약어다.
- 퍼시스턴트볼륨은 클러스터 수준의 리소스이므로 특정 네임스페이스에 생성할 수 없다. 그리고 동일한 네임스페이스의 파드에서만 사용할 수 있다.
- 접근모드로 사용되는 약어다.
- p290
- 퍼시스턴트 볼륨 클레임 참조
- 퍼시스턴트 볼륨 클레임 참조
.. volumeMounts: - name: mongodb-data mountpath: /data/db .. volumes: - name: mongodb-data persistentVolumeClaim: claimName: mongodb-pvc
- 참고 밑줄 - 김준석
6.6. 퍼시스턴트볼륨의 동적 프로비저닝 ¶
- p294
- 여전히 클러스터 관리자는 실제 스토리지를 미리 프로비저닝 해둬야 한다.
- 일 량이 줄어들지는 않는다. 하지만 한번 해놓은게 더 의미를 가지게 된다. - 김준석
- 일 량이 줄어들지는 않는다. 하지만 한번 해놓은게 더 의미를 가지게 된다. - 김준석
- 여전히 클러스터 관리자는 실제 스토리지를 미리 프로비저닝 해둬야 한다.
- p295
- 퍼시스턴트볼륨 프로비저너를 배포하고 사용자가 선택 가능한 퍼시스턴트볼륨의 타입을 하나 이상의 스토리지클래스 오브젝트로 정의할 수 있다. 사용자가 퍼시스턴트볼륨클레임에서 스토리지클래스를 참조하면 프로비저너가 퍼시스턴트 스토리지를 프로비저닝할때 이를 처리한다.
- 동작 밑줄 - 김준석
- 동작 밑줄 - 김준석
- 퍼시스턴트볼륨 프로비저너를 배포하고 사용자가 선택 가능한 퍼시스턴트볼륨의 타입을 하나 이상의 스토리지클래스 오브젝트로 정의할 수 있다. 사용자가 퍼시스턴트볼륨클레임에서 스토리지클래스를 참조하면 프로비저너가 퍼시스턴트 스토리지를 프로비저닝할때 이를 처리한다.
- p298
- p302
- 빈 문자열을 스토리지클래스 이름으로 지정하면 PVC가 새로운 PV를 동적 프로비저닝 하는 대신 미리 프로비저닝 된 PV에 바인딩된다.
- 동적 프로비저닝된 퍼시스턴트볼륨을 가져오는 것을 포함한 저체 절차를 그림에서 확인하자.
- 클러스터 관리자는 퍼시스턴트볼륨 프로비저너를 설정한다.
- 관리자는 하나 혹은 그 이상의 스토리지클래스를 생성하고 그중 하나를 기본값으로 정한다.
- 사용자는 스토리지클래스 중 하나를 참조해 PVC를 생성한다.
- 쿠버네티스는 스토리지클래스와 거기서 참조된 프로비저너를 살펴보고 프로비저너에게 pvc로 요청된 접근 모드, 스토리지 크기, 파라미터를 기반으로 새 PV를 프로비저닝하도록 요청한다.
- 프로비저너는 실제 스토리지를 프로비저닝하고 퍼시스턴트볼륨을 생성하고 PVC에 바인딩한다.
- 사용자는 PVC 이름으로 참조하는 볼륨과 파드를 생성한다.
- 어렵네 - 김준석
- 어렵네 - 김준석
- 클러스터 관리자는 퍼시스턴트볼륨 프로비저너를 설정한다.
- 빈 문자열을 스토리지클래스 이름으로 지정하면 PVC가 새로운 PV를 동적 프로비저닝 하는 대신 미리 프로비저닝 된 PV에 바인딩된다.
7.1. 컨테이너화된 애플리케이션 설정 ¶
- p306
- 파일을 이미지 안에 넣고 빌드하는 것은 애플리케이션 소스 코드에 설정 내용을 넣고 하드코딩하는 것과 비슷하다. 그로 인해 인증 정보나 암호화 키와 같이 비밀로 유지해야 하는 내용을 포함해 어떤 정보가 됐든, 해당 이미지에 접근할 수 있는 모든 사람이면 볼 수 있게 된다.
- credentail키 컨테이너에 넣고 이미지 말았다가 이미지 히스토리 싹지우고 다시 말라고 시니어 엔지니어가 슬랙서 태그걸로 호출하던게 지지난달. 본인만의 보안정책때문에... - 김준석
- credentail키 컨테이너에 넣고 이미지 말았다가 이미지 히스토리 싹지우고 다시 말라고 시니어 엔지니어가 슬랙서 태그걸로 호출하던게 지지난달. 본인만의 보안정책때문에... - 김준석
- 설정 데이터를 저장하는 쿠버네티스 리소스를 컨피그맵이라고 한다.
- configMap 줄여서 cm - 김준석
- configMap 줄여서 cm - 김준석
- 컨피그맵을 사용해 설정 데이터를 저장할지 여부에 관계없이 다음 방법을 통해 애플리케이션을 구성할 수 있다.
- 컨테이너에 명령줄 인수 전달
- 각 컨테이너를 위한 사용자 정의 환경변수 지정
- 특수한 유형의 불륨을 통해 설정 파일을 컨테이너에 마운트
- 명령줄 인수 전달 CMD, ENTRYPOINT / 환경변수 $(INTERVAL) / '/app/nginx/config/' - 김준석
- 명령줄 인수 전달 CMD, ENTRYPOINT / 환경변수 $(INTERVAL) / '/app/nginx/config/' - 김준석
- 컨테이너에 명령줄 인수 전달
- 파일을 이미지 안에 넣고 빌드하는 것은 애플리케이션 소스 코드에 설정 내용을 넣고 하드코딩하는 것과 비슷하다. 그로 인해 인증 정보나 암호화 키와 같이 비밀로 유지해야 하는 내용을 포함해 어떤 정보가 됐든, 해당 이미지에 접근할 수 있는 모든 사람이면 볼 수 있게 된다.
7.2. 컨테이너에 명령줄 인자 전달 ¶
- p307
- ENTRYPOINT와 CMD 이해
- Dockerfile에서 두 개의 지침을 다음 두 부분을 정의한다.
- ENTRYPOINT는 컨테이너가 시작될 때 호출될 명령어를 정의한다.
- CMD는 ENTRYPOINT에 전달되는 인자를 정의한다.
- ENTRYPOINT는 컨테이너가 시작될 때 호출될 명령어를 정의한다.
- Dockerfile에서 두 개의 지침을 다음 두 부분을 정의한다.
- ENTRYPOINT와 CMD 이해
- p308
- CMD 명령어를 사용해 이미지가 실행될때 실행할 명령어를 지정할 수 있지만, 올바른 방법은 ENTRYPOINT 명령어로 실행하고 기본 인자를 정의하려는 경우에만 CMD를 지정하는 것이다.
- shell과 exec 형식 간의 차이점
- 두명령어는 두 가지 서로 다른 형식을 지원한다.
- shell형식 - 예: ENTRYPOINT node app.js
- exec 형식 - 예: ENTRYPOINT [:node , "app.js"]
- exec 형식을 사용하면 셸 내부가 아니라 컨테이너 내부에서 프로세스를 직접 실행한다는게 무슨 의미지 - 서지혜
- exec 형식을 사용하면 셸 내부가 아니라 컨테이너 내부에서 프로세스를 직접 실행한다는게 무슨 의미지 - 서지혜
- shell형식 - 예: ENTRYPOINT node app.js
- 두명령어는 두 가지 서로 다른 형식을 지원한다.
1 ? Ssl 0:00 node app.js
1 ? ss 0:00 /bin/sh -c node app.js 7 ? sl 0:00 node app.js
- exec로 실행됐을때랑 shell형식으로 실행됐을때 차이 프로세스 뷰 - 김준석
- CMD 명령어를 사용해 이미지가 실행될때 실행할 명령어를 지정할 수 있지만, 올바른 방법은 ENTRYPOINT 명령어로 실행하고 기본 인자를 정의하려는 경우에만 CMD를 지정하는 것이다.
- p311
도커 쿠버네티스 설명 ENTRYPOINT command 컨테이너 안에서 실행되는 실행파일 CMD args 실행파일에 전달되는 인자 - 매핑되는 값. command: args: 로 차트에서는 쓰지 - 김준석
- 매핑되는 값. command: args: 로 차트에서는 쓰지 - 김준석
- p312
- 문자열 값을 따옴표로 묶을 필요는 없다(숫자는 묶어야 한다)
- "15" 이렇게 인자 넘길땐 숫자는 묶어라 - 김준석
- "15" 이렇게 인자 넘길땐 숫자는 묶어라 - 김준석
- 문자열 값을 따옴표로 묶을 필요는 없다(숫자는 묶어야 한다)
7.4. 컨피그맵으로 설정 분리 ¶
- p316
- p318
kubectl create configmap fortune-config --from-literal=sleep-interval=25
- 컨피그맵 키는 유효한 DNS 서브도메인(subdomain)이어야 한다(영숫자, 대시, 밑줄, 점만 포함 가능). 필요한 경우 점이 먼저 나올 수 있다.
- 정의 밑줄 - 김준석
- 정의 밑줄 - 김준석
- image: luksa/fortune:env env: - name: INTERVAL valueFrom: configMapKeyRef: name: fortune-config key: sleep-interval
- 한개만 pick - 김준석
- 한개만 pick - 김준석
kubectl create configmap my-config --from-file=config-file.conf
- p323
- 파드를 생성할 때 존재하지 않는 컨피그맵을 지정하면 어떻게 되는지 궁금할 것이다.
- config맵이 없습니다? 애초에 실행은 되나? - 김준석
- config맵이 없습니다? 애초에 실행은 되나? - 김준석
- 그런 다음 누락된 컨피그맵을 생성하면 실패했던 컨테이너는 파드를 다시 만들지 않아도 시작된다.
- 오 그럼 실행되나보네 - 김준석
- 오 그럼 실행되나보네 - 김준석
- 컨피그맵 참조를 옵션으로 표시할 수도 있다(configMapKeyRef.optional: true로 지정). 이런 경우에는 컨피그맵이 존재하지 않아도 컨테이너는 시작한다.
- 옵션 밑줄 - 김준석
- 옵션 밑줄 - 김준석
- envFrom 속성을 사용해 환경변수로 모두 노출할 수 있다.
- 파일단위로 envFrom으로 환경변수 노출한단 뜻 - 김준석
- 파일단위로 envFrom으로 환경변수 노출한단 뜻 - 김준석
- 파드를 생성할 때 존재하지 않는 컨피그맵을 지정하면 어떻게 되는지 궁금할 것이다.
- p324
- CONFIG_FOO-BAR는 대시를 가지고 있어 올바른 환경변수 이름이 아니기 때문이다. 이런 경우에 쿠버네티스는 어떤 형태로든 임의의 키로 변환하지 않는다.
- 언더바 쓰세요 - 김준석
- 언더바 쓰세요 - 김준석
- CONFIG_FOO-BAR는 대시를 가지고 있어 올바른 환경변수 이름이 아니기 때문이다. 이런 경우에 쿠버네티스는 어떤 형태로든 임의의 키로 변환하지 않는다.
- p325
args: ["$(INTERVAL)"]
- 앞에서 한 것과 동일하게 환경변수를 정의했지만 $(ENVVARIABLENAME) 문법을 사용해 쿠버네티스가 해당 변수의 값을 인자에 주입한다.
- 정의 밑줄 - 김준석
- 정의 밑줄 - 김준석
- p326
- 컨테이너에 노출시키려면, 6장에서 언급한 특수 볼륨 유형 중 하나인 컨피그맵 볼륨을 사용할 수 있다.
- 이건 안써본것 같네 - 김준석
- 이건 안써본것 같네 - 김준석
- 컨테이너에 노출시키려면, 6장에서 언급한 특수 볼륨 유형 중 하나인 컨피그맵 볼륨을 사용할 수 있다.
- p329
volumeMounts: ... - name: config mountPath: /etc/nginx/conf.d readOnly: true ... volumes: - name: config configMap: name: fortune-config ...
- configMap을 volume으로 선언 후 volumeMount로 해당 config를 mount - 김준석
- configMap을 volume으로 선언 후 volumeMount로 해당 config를 mount - 김준석
- p331
- 다행히 컨피그맵 볼륨을 컨피그맵 항목의 일부만으로 채울 수 있다.
volumes: - name: config configMap: name: fortune-config items: - key: my-nginx-config.conf path: gzip.conf
- 원래 있던 파일은 해당 파일시스템이 마운트돼 있는 동안 접근할 수 없게 된다.
- 전체 볼륨을 마운트하는 대신 volumeMount에 subPath속성으로 파일이나 디렉터리 하나를 볼륨에 마운트할 수 있다.
- 이렇게 할수 있음 - 김준석
- 이렇게 할수 있음 - 김준석
- 다행히 컨피그맵 볼륨을 컨피그맵 항목의 일부만으로 채울 수 있다.
- p333
- 하지만 개별 파일을 마운트하는 이 방법은 파일 업데이트와 관련해 상대적으로 큰 결함을 가지고 있다.
- 이렇게 할수 있으나 쓰지마세요 - 김준석
- 이렇게 할수 있으나 쓰지마세요 - 김준석
- 하지만 개별 파일을 마운트하는 이 방법은 파일 업데이트와 관련해 상대적으로 큰 결함을 가지고 있다.
- p334
- 환경변수 또는 명령줄 인수를 설정 소스로 사용할 때의 단점은 프로세스가 실행되고 있는 동안에 업데이트할 수 없다는 것이다.
- command나 entry-point로는 별로 좋지 않다는 거지 - 김준석
- command나 entry-point로는 별로 좋지 않다는 거지 - 김준석
- 애플리케이션이 설정을 다시 읽는 기능을 지원하는 않는 경우에 심각한 문제가 발생한다. 이로 인해 서로 다른 설정을 가진 인스턴스가 실행되는 결과를 초래한다.
- command가 다르단거지 - 김준석
- command가 다르단거지 - 김준석
- 애플리케이션이 다시 읽기를 지원한다면, 컨피그맵을 수정하는 것은 그리 큰문제는 아니다. 하지만 컨피그맵 볼륨의 파일이 실행 중인 모든 인스턴스에 걸쳐 동기적으로 업데이트되지 않기 때문에, 개별 파드의 파일이 최대 1분 동안 동기화되지 않는 상태로 있을 수 있음을 알고 있어야 한다.
- command로 실행되는걸 env로 바꾸고 reload하는걸 생각해봤는데 생각보다 어렵겠네 - 김준석
- command로 실행되는걸 env로 바꾸고 reload하는걸 생각해봤는데 생각보다 어렵겠네 - 김준석
- 환경변수 또는 명령줄 인수를 설정 소스로 사용할 때의 단점은 프로세스가 실행되고 있는 동안에 업데이트할 수 없다는 것이다.
7.5. 시크릿으로 민감함 데이터를 컨테이너에 전달 ¶
- p337
- 쿠버네티스는 시크릿이라는 별도 오브젝트를 제공한다.
- secret - 김준석
- secret - 김준석
- 시크릿을 다음과 같은 상황에서 사용할 수 있다.
- 환경변수로 시크릿 항목을 컨테이너에 전달
- 시크릿 항목을 볼륨 파일로 노출
- 활용 목록 - 김준석
- 활용 목록 - 김준석
- 환경변수로 시크릿 항목을 컨테이너에 전달
- 또한 노드 자체적으로 시크릿을 항상 메모리에만 저장되게 하고 물리 저장소에 기록되지 않도록 한다.
- 이건 개발자들이 실행할때만 안다는 그것 - 김준석
- 이건 개발자들이 실행할때만 안다는 그것 - 김준석
- 마스터 노드에는 시크릿을 암호화되지 않은 형식으로 저장하므로, 시크릿에 저장한 민감한 데이터를 보호하려면 마스터 노드를 보호하는 것이 필요하다.(base64로 인코딩으로 바뀜)
- 쿠버네티스는 시크릿이라는 별도 오브젝트를 제공한다.
- p339
- 시크릿이 갖고 있는 세 가지 항목은 파드 안에서 쿠버네티스 API 서버와 통신할 때 필요한 모든 것을 나타낸다.
- 시크릿이 갖고 있는 세 가지 항목은 파드 안에서 쿠버네티스 API 서버와 통신할 때 필요한 모든 것을 나타낸다.
- p341
- p343
- Base64 인코딩을 사용하는 까닭은 간단하다. 시크릿 항목에 일반 텍스트뿐만 아니라 바이너리 값도 담을 수 있기 때문이다.
- 복호화도 쉽지 왜 썼냐.. - 김준석
- 복호화도 쉽지 왜 썼냐.. - 김준석
- Base64 인코딩을 사용하는 까닭은 간단하다. 시크릿 항목에 일반 텍스트뿐만 아니라 바이너리 값도 담을 수 있기 때문이다.
- p345
... - name: certs mountPath: /etc/nginx/certs/ readOnly: true ... - name: certs secret: secretname: fortune-https
- 활용 예제 밑줄 - 김준석
- 활용 예제 밑줄 - 김준석
- p348
- 인증서와 개인 키를 secret 볼륨에 마운트해 파드에 성공적으로 전달했다. secret 볼륨은 시크릿 파일을 저장하는 데 인메모리 파일시스템(tmpfs)을 사용한다.
- 메모리 파일 시스템. linux 설치할때도 씀 - 김준석
- 메모리 파일 시스템. linux 설치할때도 씀 - 김준석
env: - name: FOO_SECRET valueFrom: secretKeyRef: name: fortune-https key: foo
- 이것은 INTERVAL 환경변수를 설정하는 것과 거의 비슷하다. 단지 이번에는 컨피그맵을 참조하는 데 confgMapKeyRef 대신 secretKeyRef를 사용해 시크릿을 참조한다는 점이 다르다.
- 비슷하네 - 김준석
- 비슷하네 - 김준석
- 이것은 INTERVAL 환경변수를 설정하는 것과 거의 비슷하다. 단지 이번에는 컨피그맵을 참조하는 데 confgMapKeyRef 대신 secretKeyRef를 사용해 시크릿을 참조한다는 점이 다르다.
- 인증서와 개인 키를 secret 볼륨에 마운트해 파드에 성공적으로 전달했다. secret 볼륨은 시크릿 파일을 저장하는 데 인메모리 파일시스템(tmpfs)을 사용한다.
- p350
$ kubectl create secret docker-registry mydockerhubsecret \ --docker-username=myusername --docker-password=mypassword \ --docker-email=my.email@provider.com
- docker-registry secret 예제 - 김준석
- docker-registry secret 예제 - 김준석
imagePullScrets: - name: mydockerhubsecret
- 시크릿을 서비스어카운트에 추가해 모든 파드에 자동으로 추가될 수 있게 하는 법을 배울 것이다.
- sa에 추가는 추후에 - 김준석
- sa에 추가는 추후에 - 김준석
8.1. Downward API로 메타데이터 전달 ¶
- p354
- p355
- Downward API를 사용하면 파드 자체의 메타데이터를 해당 파드 내에서 실행 중인 프로세스에 노출할 수 있다. 현재 다음 정보를 컨테이너에 전달 할 수 있다.
- 파드의 이름
- 파드의 주소
- 파드가 속한 네임스페이스
- 파드가 실행 중인 노드의 이름
- 파드가 실행 중인 서비스 어카운트 이름
- 각컨테이너의 CPU와 메모리 요청
- 각 컨테이너의 CPU와 메모리 제한
- 파드의 레이블
- 파드의 어노테이션
- CPU와 메모리 요청은 대부분 어플리케이션의 heap 사이즈 조정하는데 쓸수 있겠네 - 김준석
- CPU와 메모리 요청은 대부분 어플리케이션의 heap 사이즈 조정하는데 쓸수 있겠네 - 김준석
- 파드의 이름
- Downward API를 사용하면 파드 자체의 메타데이터를 해당 파드 내에서 실행 중인 프로세스에 노출할 수 있다. 현재 다음 정보를 컨테이너에 전달 할 수 있다.
- p356
env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name ... - name: POD_IP valueFrom: fieldRef: fieldPath: status.podIP ...
- yaml 예시 - 김준석
- p359
- 환경변수 대신 파일로 메타데이터를 노출하려는 경우 downwardAPI 볼륨을 정의해 컨테이너에 마운트할 수 있다.
- 환경변수 대신 파일로 메타데이터를 노출하려는 경우 downwardAPI 볼륨을 정의해 컨테이너에 마운트할 수 있다.
... volumeMounts: - name: downward mountPath: /etc/downward volumes: - name: downard downwardAPI: items: - path: "podName" fieldRef: fieldPath: metadata.name ...
- 정의 밑줄 - 김준석
- p362
- 보다시피 각 레이블/어노테이션은 별도의 줄에 키=값 형식으로 저장된다. 값이 여러줄인 경우 줄 바꾸기 문자가 \n으로 표시돼 한 줄로 기록된다.
- 그래서 값을 가져오면 꼭 vim이나 기타 프로그램에서 줄을 없애고 이상한게 없는지 봐야할때가 있지 - 김준석
- 그래서 값을 가져오면 꼭 vim이나 기타 프로그램에서 줄을 없애고 이상한게 없는지 봐야할때가 있지 - 김준석
- 보다시피 각 레이블/어노테이션은 별도의 줄에 키=값 형식으로 저장된다. 값이 여러줄인 경우 줄 바꾸기 문자가 \n으로 표시돼 한 줄로 기록된다.
- p363
8.2. 쿠버네티스 API 서버와 통신하기 ¶
- p364
- 애플리케이션이 다른 리소스의 정보가 필요하거나 가능한 한 최신 정보에 접근해야 하는 경우 API 서버와 직접 통신해야 한다.
- 사실 어디다 사용하는건지 모르겠다. - 김준석
- 사실 어디다 사용하는건지 모르겠다. - 김준석
kubectl cluster-info
를 실행해 URL을 얻을수 있다.
- curl의 --insecure 옵션을 사용해 서버 인증서 확인을 건너뛰도록 시도해볼 수 있지만 원하는 결과를 얻지는 못한다.
- --insecure 많이 쓰지 난 docker-registry 에 접근할때 많이 쓴듯 - 김준석
- --insecure 많이 쓰지 난 docker-registry 에 접근할때 많이 쓴듯 - 김준석
$ kubectl proxy
and$ curl localhost:8001
- kube-proxy에 접근 - 김준석
- kube-proxy에 접근 - 김준석
- 초기 버전의 쿠버네티스에 도입된 가장 일반적인 리소스 유형들은 특정 그룹에 속하지 않는다. APi 그룹은 나중에 도입됐다. API 그룹이 없는, 이런 초기 리소스 유형은 이제 core API 그룹에 속하는 것으로 간주된다.
- v1 기준이 뭘까하는걸 풀어주는 항목이네 - 김준석
- v1 기준이 뭘까하는걸 풀어주는 항목이네 - 김준석
$ curl http://localhost:8001/apis/batch/v1
- 호출할수 있는 create나 delete같은걸 보여줌. pod나 job의 status도 어떤 카테고리가 있는지 보여줌 - 김준석
- 호출할수 있는 create나 delete같은걸 보여줌. pod나 job의 status도 어떤 카테고리가 있는지 보여줌 - 김준석
$ curl http://localhost:8001/apis/batch/v1/jobs
- kubectl의 get jobs 는 이런 API를 써서 보여주겠지? - 김준석
- kubectl의 get jobs 는 이런 API를 써서 보여주겠지? - 김준석
- 애플리케이션이 다른 리소스의 정보가 필요하거나 가능한 한 최신 정보에 접근해야 하는 경우 API 서버와 직접 통신해야 한다.
- p371
- 파드 내부에서 API서버와 통신하려면 다음 세 가지를 처리해야 한다.
- API서버의 위치를 찾아야 한다.
- API 서버와 통신하고 있는지 확인해야 한다.
- API 서버로 인증해야 한다. 그렇지 않으면 볼 수도 없고 아무것도 할 수 없다.
https://kubernets
/ -k( -- insecure) / 인증서 및 토큰 필요 - 김준석
- API서버의 위치를 찾아야 한다.
- 파드 내부에서 API서버와 통신하려면 다음 세 가지를 처리해야 한다.
- p377
- 파드 내에서 실행 중인 애플리케이션이 쿠버네티스 API에 적절히 액세스 할 수 있는 방법을 정리해보자.
- API서버의 인증서가 인증 기관으로부터 서명됐는지 검증, ca, cart 파일임.
- 애플리케이션은 token을 Authroization 헤더에 bearer 토큰으로 넣어 전송해야함
- namespace 파일은 파드의 네임스페이스 안에 있는 API오브젝트의 CRUD 작업을 수행할때 네임스페이스를 API서버로 전달하는데 사용해야 한다.
- 일반적인 인증 절차 - 김준석
- 일반적인 인증 절차 - 김준석
- API서버의 인증서가 인증 기관으로부터 서명됐는지 검증, ca, cart 파일임.
- 파드 내에서 실행 중인 애플리케이션이 쿠버네티스 API에 적절히 액세스 할 수 있는 방법을 정리해보자.
- p378
- p381
- curl은 일반 HTTP 요청을 앰배서더 컨테이너 내에서 실행 중인 프록시로 전송한 다음, 프록시는 HTTPS 요청을 API 서버로 전송하며, 토큰을 전송해 클라이언트 인증을 처리하고 서버의 인증서를 검증해 서버의 신원을 확인한다.
- ca는 proxy 컨테이너니까 인증 될테고, 시크릿에 있는 default-token으로 token의 역을 해서 처리한다는것 같네 - 김준석
- ca는 proxy 컨테이너니까 인증 될테고, 시크릿에 있는 default-token으로 token의 역을 해서 처리한다는것 같네 - 김준석
- curl은 일반 HTTP 요청을 앰배서더 컨테이너 내에서 실행 중인 프록시로 전송한 다음, 프록시는 HTTPS 요청을 API 서버로 전송하며, 토큰을 전송해 클라이언트 인증을 처리하고 서버의 인증서를 검증해 서버의 신원을 확인한다.
- p382
- 그러나 단순한 API 요청 이상을 수행하려면 쿠버네티스 API 클라이언트 라이브러리 중 하나를 사용하는 것이 좋다.
- 클라리언트 라이브러리가 참 많네 - 김준석
- 클라리언트 라이브러리가 참 많네 - 김준석
- 그러나 단순한 API 요청 이상을 수행하려면 쿠버네티스 API 클라이언트 라이브러리 중 하나를 사용하는 것이 좋다.
9. 디플로에먼트: 선언적 애플리케이션 업데이트 ¶
- p389
- 쿠버네티스 클러스터에서 실행되는 애플리케이션을 업데이트하는 방법과 쿠버네티스가 어떻게 무중단 업데이트 프로세스로 전환하는데 도움을 주는지 설명할 것이다.
- 9장 목적 - 김준석
- 9장 목적 - 김준석
- 쿠버네티스 클러스터에서 실행되는 애플리케이션을 업데이트하는 방법과 쿠버네티스가 어떻게 무중단 업데이트 프로세스로 전환하는데 도움을 주는지 설명할 것이다.
9.1. 파드에서 실행 중인 애플리케이션 업데이트 ¶
- p391
- 모든 파드를 업데이트하는 방법에는 두 가지가 있다. 다음 중 하나를 수행할 수 있다.
- 기본 파드를 모두 삭제한 다음 새 파드를 시작한다.
- 새로운 파드를 시작하고, 가동하면 기존 파드를 삭제한다. 새 파드를 모두 추가한 다음 한꺼번에 기존 파드를 삭제하거나 순차적으로 새 파드를 추가하고 기존 파드를 점진적으로 제거해 이 작업을 수행할 수 있다.
- 세가지 이미지 업데이트 방법 - 김준석
- 세가지 이미지 업데이트 방법 - 김준석
- 기본 파드를 모두 삭제한 다음 새 파드를 시작한다.
- 모든 파드를 업데이트하는 방법에는 두 가지가 있다. 다음 중 하나를 수행할 수 있다.
- p392
- 새 파드 모두 실행되면 그림과 같이 서비스의 레이블 셀렉터를 변경하고 서비스를 새 파드로 전환할 수 있다. 이것을 블루-그린 디플로이먼트라고 한다.
- 블루 그린은 또 무슨뜻일까 - 김준석
- 배포전략중 하나입니다. https://martinfowler.com/bliki/BlueGreenDeployment.html - bluemir
- 배포전략중 하나입니다. https://martinfowler.com/bliki/BlueGreenDeployment.html - bluemir
- 블루 그린은 또 무슨뜻일까 - 김준석
- 새 파드가 모두 실행된 후 이전파드를 한 번에 삭제하는 방법 대신 파드를 단계별로 교체하는 롤링 업데이트를 수행할 수도 있다.
- 기본 설명 - 김준석
- 기본 설명 - 김준석
- 새 파드 모두 실행되면 그림과 같이 서비스의 레이블 셀렉터를 변경하고 서비스를 새 파드로 전환할 수 있다. 이것을 블루-그린 디플로이먼트라고 한다.
9.2. 레플리케이션컨트롤러로 자동 롤링 업데이트 수행 ¶
- p394
- kubectl을 사용해 업데이트를 수행하면 프로세스가 훨씬 간단해지지만 나중에 볼 수 있듯이 이방법도 이제는 애플리케이션을 업데이트하는 오래된 방법이 됐다.
- 이건 문서로만봤지 한번도 실전서 못봄 - 김준석
- 이건 문서로만봤지 한번도 실전서 못봄 - 김준석
- kubectl을 사용해 업데이트를 수행하면 프로세스가 훨씬 간단해지지만 나중에 볼 수 있듯이 이방법도 이제는 애플리케이션을 업데이트하는 오래된 방법이 됐다.
- p396
- YAML 파일에는 대시 3개가 있는 줄로 구분해 여러 리소스 정의를 포함할 수 있다.
- 메모 - 서지혜
- 메모 - 서지혜
- YAML 파일에는 대시 3개가 있는 줄로 구분해 여러 리소스 정의를 포함할 수 있다.
- p397
- p398
$ kubectl rolling-update kubia-v1 kubia-v2 --image=luksa/kubia:v2
- kubia-v1 replicaset을 v2로 바꾸고 이미지는 v2 tag를 쓰자 - 김준석
- kubia-v1 replicaset을 v2로 바꾸고 이미지는 v2 tag를 쓰자 - 김준석
- p400
- kubectl이 레플리케이션컨트롤러의 셀렉터를 변경하기 전에 실행 중인 파드의 레이블을 먼저 수정하기 때문이다.
- 컨트롤러는 첫번째 v2파드를 만든다. kubectl은 이전 레플리케이션컨트롤러를 하나씩 스케일 다운한다.
- kubectl이 롤링 업데이트를 계속하면 v2 파드에 대한 요청 비율이 점점 더 높아지기 시작한다. 결국 이전 레플리케이션 컨트롤러의 파드가 0으로 스케일 다운되며 마지막 v1 파드가 삭제돼 서비스가 이제 v2파드에 의해서만 지원된다는 것을 의미한다.
- kubectl이 레플리케이션컨트롤러의 셀렉터를 변경하기 전에 실행 중인 파드의 레이블을 먼저 수정하기 때문이다.
- p403
- 롤링 업데이트의 모든 단계를 수행하는 것이 kubectl 클라이언트라는 것을 알아차렸을 것이다.
- 지금은 업데이트가 원활하게 진행됐지만 kubectl이 업데이트를 수행하는 동안 네트워크 연결이 진행됐지만 kubectl이 업데이트를 수행하는 동안 네트워크 연결이 끊어진다면 어떨까?
- k8s도 이렇게 어설플때도 있었군 - 김준석
- k8s도 이렇게 어설플때도 있었군 - 김준석
- 롤링 업데이트의 모든 단계를 수행하는 것이 kubectl 클라이언트라는 것을 알아차렸을 것이다.
- p404
9.3. 애플리케이션을 선언적으로 업데이트하기 위한 디플로이먼트 사용하기 ¶
- 디플로이먼트는 낮은 수준의 개념으로 간주되는 레플리케이션컨트롤러 또는 레플리카셋을 통해 수행하는 대신 애플리케이션을 배포하고 선언적으로 업데이트하기 위한 높은 수준의 리소스다.
- 좀더 추상적? 인 개념이겠지 - 김준석
- 좀더 추상적? 인 개념이겠지 - 김준석
apiVersion: apps/v1beta1 kind: Deployment metadata: name: kubia spec: replicas: 3 template: metadata: name: kubia labels: app: kubia spec: containers: - image: luksa/kubia:v1 name: nodejs
- yaml 참고 - 김준석
- p407
$ kubectl rollout status deployment kubia
- rollout은 배포된걸 얘기하는건가 - 김준석
- rollout은 배포된걸 얘기하는건가 - 김준석
- p408
- 디플로이먼트는 파드를 직접 관리하지 않는다. 대신 레플리카셋을 생성하고 이들이 파드를 관리하도록 맡겨둔다.
- k8s가 다해줘라 - 김준석
- k8s가 다해줘라 - 김준석
- 디플로이먼트는 파드를 직접 관리하지 않는다. 대신 레플리카셋을 생성하고 이들이 파드를 관리하도록 맡겨둔다.
- p409
- 디플로이먼트 리소스에 정의된 파드 템플릿을 수정하기만 하면 쿠버네티스가 실제 시스템 상태를 리소스에 정의된 산태로 만드는 데 필요한 모든 단계를 수행한다. 레플리케이션컨트롤러 또는 레플리카셋을 스케일 업 또는 스케일 다운하는 것과 마찬가지로 디플로이먼트 파드 템플릿에서 새 이미지 태그를 참조해 시스템이 의도하는 상태가 될수 있도록 쿠버네티스에 맡기면 된다.
- kubectl이 아닌 k8s서버에 맡긴다는 의미도 포함이겠지? - 김준석
- kubectl이 아닌 k8s서버에 맡긴다는 의미도 포함이겠지? - 김준석
- 새로운 상태를 달성하는 방법은 디플로이먼트에 구성된 디플로이먼트 전략에 의해 결정된다. 기본은 RollingUpdate라는 롤링 업데이트 전략이다. 대안으로 Recreate 전략이 있는데, 레플리케이션컨트롤러의 파드 템플릿을 수정한 후 모든 파드를 샂게하는 것과 마찬가지로 한 번에 기존 모든 파드를 삭제한 뒤 새로운 파드를 만든다.
- 디플로이먼트 리소스에 정의된 파드 템플릿을 수정하기만 하면 쿠버네티스가 실제 시스템 상태를 리소스에 정의된 산태로 만드는 데 필요한 모든 단계를 수행한다. 레플리케이션컨트롤러 또는 레플리카셋을 스케일 업 또는 스케일 다운하는 것과 마찬가지로 디플로이먼트 파드 템플릿에서 새 이미지 태그를 참조해 시스템이 의도하는 상태가 될수 있도록 쿠버네티스에 맡기면 된다.
- p410
$ kubectl patch deployment kubia -p '{"spec": {"minReadySeconds": 10}}'
- 디플로이먼트 오브젝트의 전체 YAML을 편집하거나 patch 명령어를 사용해 이미지를 변경하는 대신 kubectl set image 명령어를 사용해 컨테이너가 포함된 모든 리소스를 수정할 수 있다.
$ kubectl set image deployment kubia nodejs=luksa/kubia:v2
- 디플로이먼트와 그 외의 리소스를 수정하는 방법
- kubectl edit
- kubectl patch
- kubectl apply
- kubectl replace
- kubectl set image
- kubectl edit
- p415
$ kubectl rollout status deployment kubia
- 배포 현황 치트 시트 - 김준석
- 배포 현황 치트 시트 - 김준석
- p417
- p419
- 롤링 업데이트 속도 구성을 위한 속성
- maxSurge : 디플로이먼트가 의도하는 레플리카 수보다 얼마나 많은 파드 인스턴스 수를 허용할 수 있는지 결정한다.백분률 or 절대값
- maxUnavailable : 업데이트 중에 의도하는 레플리카 수를 기준으로 사용할 수 없는 파드 인스턴스 수를 결정. 백분률 or 절대값.
- maxSurge : 디플로이먼트가 의도하는 레플리카 수보다 얼마나 많은 파드 인스턴스 수를 허용할 수 있는지 결정한다.백분률 or 절대값
- 롤링 업데이트 속도 구성을 위한 속성
- p422
$ kubectl rollout pause deployment kubia
- 카나리 릴리스를 효과적으로 실행 할 수 있다.
$ kubectl rollout resume deployment kubia
- p424
- minReadySeconds가 지나기 전에 새 파드가 제대로 작동하지 않고 레디니스 프로브가 실패하기 시작하면 새 버전의 롤아웃이 효과적으로 차단된다.
- maxSurge / maxUnavailable 규칙에 의해서 - 김준석
- maxSurge / maxUnavailable 규칙에 의해서 - 김준석
- 적절하게 구성된 레드니스 프로브와 적절한 minReadySeconds 설정으로 쿠버네티스는 버그가 있는 버전 v3를 배포하지 못하게 했을 것이다.
- minReadySeconds가 지나기 전에 새 파드가 제대로 작동하지 않고 레디니스 프로브가 실패하기 시작하면 새 버전의 롤아웃이 효과적으로 차단된다.
- p429
- 기본적으로 롤아웃이 10분 동안 진행되지 않으면 실패한 것으로 간주된다. kubectl descirbe deployement 명령어를 사용하면 예제와 같이 ProgressDeadlineExceeded 조건이 표시된다.
- 기본적으로 롤아웃이 10분 동안 진행되지 않으면 실패한 것으로 간주된다. kubectl descirbe deployement 명령어를 사용하면 예제와 같이 ProgressDeadlineExceeded 조건이 표시된다.
10.2. 스테이트풀셋 이해하기 ¶
- p438
- p439
- 애플리케이션의 경우 새 인스턴스가 이전 인스턴스와 완전히 같은 상태와 아이덴티티를 가져야 함을 의미한다.
- RS과 다른점 - 김준석
- RS과 다른점 - 김준석
- 애플리케이션의 경우 새 인스턴스가 이전 인스턴스와 완전히 같은 상태와 아이덴티티를 가져야 함을 의미한다.
- p440
- 스테이트풀 파드가 종료되면 새로운 파드 인스턴스는 교체되는 파드와 동일한 이름, 네트워크 아이덴티티, 상태 그대로 다른 노드에서 되살아나야 한다.
- 스테이트풀셋으로 생성된 파드는 서수 인덱스가 할당되고 파드의 이름과 호스트 이름, 안정적인 스토리지를 붙이는 데 사용된다.
- kubia-0, kubia-1,kubia-2 ... - 김준석
- kubia-0, kubia-1,kubia-2 ... - 김준석
- 스테이트풀 파드가 종료되면 새로운 파드 인스턴스는 교체되는 파드와 동일한 이름, 네트워크 아이덴티티, 상태 그대로 다른 노드에서 되살아나야 한다.
- p441
- 스테이트풀셋은 거버닝 헤드리스 서비스를 생성해서 각 파드에게 실제 네트워크 아이덴티티를 제공해야 한다.
- SRV 로 kubia.default.svc.cluster.local 를 기본으로 kubia-0.kubia... - 김준석
- SRV 로 kubia.default.svc.cluster.local 를 기본으로 kubia-0.kubia... - 김준석
- 스테이트풀셋은 거버닝 헤드리스 서비스를 생성해서 각 파드에게 실제 네트워크 아이덴티티를 제공해야 한다.
- p442
- 하지만 레플리카셋과 달리 교체된 파드는 사라진 파드와 동일한 이름과 호스트 이름을 갖는다.
- kubia-0이 없어지면 kubia-0이 생성됨 - 김준석
- kubia-0이 없어지면 kubia-0이 생성됨 - 김준석
- 하지만 레플리카셋과 달리 교체된 파드는 사라진 파드와 동일한 이름과 호스트 이름을 갖는다.
- p443
- 스테이트 풀셋을 스케일링하면 사용하지 않는 다음 서수 인덱스를 갖는 새로운 파드 인스턴스를 생성한다. 인스턴스 두 개에서 세 개로 스케일업하면 새로운 인스턴스는 인덱스 2를 부여받는다.
- 스테이트 풀셋을 스케일링하면 사용하지 않는 다음 서수 인덱스를 갖는 새로운 파드 인스턴스를 생성한다. 인스턴스 두 개에서 세 개로 스케일업하면 새로운 인스턴스는 인덱스 2를 부여받는다.
- p445
- 스테이트 풀 파드의 스토리지는 영구적이어야 하고 파드와는 분리돼야 한다.
- 스테이트풀셋이 파드를 생성하는 것과 같은 방식으로 퍼시스턴트볼륨클레임 또한 생성해야 한다. 이런 이유로 스테이트풀셋은 각 파드와 함께하는 퍼시스턴트볼륨클레임을 복제하는 하나 이상의 볼륨 클레임 템플릿을 가질 수 있따.
- 스테이트 풀 파드의 스토리지는 영구적이어야 하고 파드와는 분리돼야 한다.
- p446
- 스테이트풀셋을 하나 스케일 업하면 두 개 이상의 API 오브젝트가 생성된다. 하지만 스케일 다운을 할 때 파드만 삭제하고 클레임은 남겨둔다.
- 데이터가 날아가기 때문에. 다시 scale up하면 다시 붙는다 - 김준석
- 데이터가 날아가기 때문에. 다시 scale up하면 다시 붙는다 - 김준석
- 스테이트풀셋을 하나 스케일 업하면 두 개 이상의 API 오브젝트가 생성된다. 하지만 스케일 다운을 할 때 파드만 삭제하고 클레임은 남겨둔다.
- p448
- 스테이트 풀셋은 교체 파드를 생성하기 전에 파드가 더 이상 실행 중이지 않는다는 점을 절대적으로 확신해야 한다는 뜻이다.
- 아이덴티때문에 복잡할듯 - 김준석
- 아이덴티때문에 복잡할듯 - 김준석
- 스테이트 풀셋은 교체 파드를 생성하기 전에 파드가 더 이상 실행 중이지 않는다는 점을 절대적으로 확신해야 한다는 뜻이다.
10.3. 스테이트풀셋 사용하기 ¶
- p450
- 애플리케이션을 배포하려면 다른 유형의 오브젝트 두 가지를 생성해야 한다.
- 데이터 파일을 저장하기 위한 퍼시스턴트볼륨
- 스테이트풀셋에 필요한 거버닝 서비스
- 스테이트풀셋 자체
- 데이터 파일을 저장하기 위한 퍼시스턴트볼륨
- 애플리케이션을 배포하려면 다른 유형의 오브젝트 두 가지를 생성해야 한다.
- p425
- clusterIp 필드를 None으로 설정하면 헤드리스 서비스가 된다.
- clusterIp 필드를 None으로 설정하면 헤드리스 서비스가 된다.
10.5. 스테이트풀셋이 노드 실패를 처리하는 과정 이해하기 ¶
- p467
- 쿠버네티스 버전 1.7 부터 스테이트풀셋도 디플로이먼트나 데몬셋과 같은 방식으로 롤링 업데이트를 지원한다.
- 쿠버네티스 버전 1.7 부터 스테이트풀셋도 디플로이먼트나 데몬셋과 같은 방식으로 롤링 업데이트를 지원한다.
- p469
11. 쿠버네티스 내부 이해 ¶
- p475
- 시스템의 기능을 잘 이해할 때까지 시스템의 동작 방식을 자세히 다루는 것이 합리적이지 않기 때문이다
- 기술 서적을 읽을 땐 필요한 부분으로 건너뛰면서 읽는 방식이 더 효율적 인 것 같다 - 서지혜
- 기술 서적을 읽을 땐 필요한 부분으로 건너뛰면서 읽는 방식이 더 효율적 인 것 같다 - 서지혜
- 시스템의 기능을 잘 이해할 때까지 시스템의 동작 방식을 자세히 다루는 것이 합리적이지 않기 때문이다
11.1. 아키텍쳐 이해 ¶
- p476
- 컨트롤 플레인은 클러스터 기능을 제어하고 전체 클러스터가 동작하게 만드는 역할을 한다.
etcd 분산 저장 스토리지 API 서버 스케쥴러 컨트롤 매니저
- 컨테이너를 실행하는 작업은 각 워커 노드에서 실행되는 구성 요소가 담당한다.
Kubelet Kube-proxy 컨테이너 런타임(Docker, rkt 외 기타)
- 애드온 구성 요소
쿠버네티스 DNS 서버 대시보드 인그레스 컨트롤러 힙스터 컨테이너 네트워크 인터페이스 플러그인
- 컨트롤 플레인은 클러스터 기능을 제어하고 전체 클러스터가 동작하게 만드는 역할을 한다.
11.1.1. 쿠버네티스 구성 요소의 분산 특성 ¶
- p477
- 구성 요소들은 모두 개별 프로세스로 실행된다.
- 구성 요소들은 모두 개별 프로세스로 실행된다.
- p478
- p479
- kubelet은 항상 일반 시스템구성 요소로 실행되는 유일한 구성 요소이며, kubelet이 다른 구성 요소를 파드로 실행한다.
- kubelet은 항상 일반 시스템구성 요소로 실행되는 유일한 구성 요소이며, kubelet이 다른 구성 요소를 파드로 실행한다.
11.1.2. 쿠버네티스가 etcd를 사용하는 방법 ¶
- p480
- 생성한 모든 오브젝트는 API서버가 다시 시작되거나 실패하더라도 유지하기 위해 매니페스트가 영구적으로 저장될 필요가 있다. 이를 위해 쿠버네티스는 빠르고, 분산해서 저장되며, 일관된 키-값 저장소를 제공하는 etcd를 사용한다. 부산돼 있기 때문에 둘 이상의 etcd 인스턴스를 실행해 고가용성과 우수한 성능을 제공할 수 있다.
-
$ etcdctl ls /registry
- 치트 밑줄 - 김준석
- 치트 밑줄 - 김준석
- 생성한 모든 오브젝트는 API서버가 다시 시작되거나 실패하더라도 유지하기 위해 매니페스트가 영구적으로 저장될 필요가 있다. 이를 위해 쿠버네티스는 빠르고, 분산해서 저장되며, 일관된 키-값 저장소를 제공하는 etcd를 사용한다. 부산돼 있기 때문에 둘 이상의 etcd 인스턴스를 실행해 고가용성과 우수한 성능을 제공할 수 있다.
- p483
- 쿠버네티스는 다른 모든 구성 요소가 API 서버를 통하도록 함으로써 이를 개선했다. API 서버 한곳에서 낙관전 잠금 매커니즘을 구현해서 클러스터의 상태를 업데이트하기 때문에, 오류가 발생할 가능성을 줄이고 항상 일관성을 가질 수 있다.
- 고가용성을 보장하기 위해서는 두개 이상의 etcd 인스턴스를 실행하는 것이 일반적이다.여러 etcd 인스턴스는 일관성을 유지해야한다. 이러한 분산 시스템은 실제 상태가 무엇인지 합의에 도달해야 한다. etcd는 RAFT 합의 알고리즘을 사용해 어느 순간이든 각 노드 상태가 대다수의 노드가 동의하는 현재 상태이거나 이전에 동의된 상태 중에 하나임을 보장한다.
- etcd 인스턴스를 일반적으로 홀수로 배포한다.
- 쿠버네티스는 다른 모든 구성 요소가 API 서버를 통하도록 함으로써 이를 개선했다. API 서버 한곳에서 낙관전 잠금 매커니즘을 구현해서 클러스터의 상태를 업데이트하기 때문에, 오류가 발생할 가능성을 줄이고 항상 일관성을 가질 수 있다.
11.1.3. API 서버의 기능 ¶
- p485
- 클러스터 상태를 조회하고 변경하기 위해 RESTful API로 CRUD 인터페이스를 제공한다. 상태는 etcd 안에 저장한다.
- 오브젝트 유효성 검사 작업도 수행하기 때문에 잘못 설정된 오브젝트를 저장할 수 없다. 유효성 검사와 함께 낙관적 잠금도 처리하기 때문에 동시에 업데이터가 발생하더라도 다른 클라이언트에 의해 오브젝트의 변경 사항이 재정의 되지 않는다.
- 클러스터 상태를 조회하고 변경하기 위해 RESTful API로 CRUD 인터페이스를 제공한다. 상태는 etcd 안에 저장한다.
- p486
- 먼저 API 서버는 요청을 보낸 클라이언트를 인증해야 한다. 이 작업은 API 서버에 구성된 하나 이상의 플러그인에 의해 수행된다.
- API 서버는 인증 플러그인 외에도 하나 이상의 인가 플러그인을 사용하도록 설정돼 있다. 이 작업은 인증된 사용자가 요청한 작업이 요청한 리소스를 대상으로 수행할 수 있는지를 판별한다.
- 리소스를 생성, 수정, 삭제하려는 요청인 경우에 해당 요청은 어드미션 컨트롤로 보내진다.
- 해당 리소스는 모든 어드미션 컨트롤 플러그인을 통과한다.
- https://kubernetes.io/docs/admin/admission-controllers/에서 찾아볼 수 있다.
- 요청이 모든 어드미션 컨트롤 플러그인을 통과하면, API 서버는 오브젝트의 유효성을 검증하고 etcd에 저장한다. 그리고 클라이언트에 응답을 반환한다.
- 먼저 API 서버는 요청을 보낸 클라이언트를 인증해야 한다. 이 작업은 API 서버에 구성된 하나 이상의 플러그인에 의해 수행된다.
11.1.4. API 서버가 리소스 변경을 클라이언트에 통보하는 방법 이해 ¶
- p487
- API서버는 이런 커트롤러에 무엇을 해야 하는지 알려주지 않는다. 단지 컨트롤러와 다른 구성 요소가 배포된 리소스의 변경 사항을 관찰할 수 있도록 하면 된다.
- 클라이언트는 API 서버에 http 연결을 맺고 변경 사항을 감지한다. 이 연결을 통해 클라이언트 감시 대상 오브젝트의 변경을 알 수 있는 스트림을 받는다. 오브젝트가 갱신될 때마다, 서버는 오브젝트를 감시하고 있는 연결된 모든 클라이언트에게 오브젝트의 새로운 버전을 보낸다.
- 저는 GRPC 연결이라고 알고 있는데 과거에는 달랐을수도 있겠네요 - bluemir
- 저는 GRPC 연결이라고 알고 있는데 과거에는 달랐을수도 있겠네요 - bluemir
- API서버는 이런 커트롤러에 무엇을 해야 하는지 알려주지 않는다. 단지 컨트롤러와 다른 구성 요소가 배포된 리소스의 변경 사항을 관찰할 수 있도록 하면 된다.
11.1.5. 스케줄러 이해 ¶
- p489
- 스케줄러는 선택된 노드에 파드를 실행하도록 지시하지 않는다. 단지 스케줄러는 API 서버로 파드 정의를 갱신한다. API 서버는 kubelet에 파드가 스케줄링된 것을 통보한다.대상 노드의 kubelet은 파드가 해당 노드에 스케줄링된 것을 확인하자마자 파드의 컨테이너를 생성하고 실행한다.
- 스케줄러는 선택된 노드에 파드를 실행하도록 지시하지 않는다. 단지 스케줄러는 API 서버로 파드 정의를 갱신한다. API 서버는 kubelet에 파드가 스케줄링된 것을 통보한다.대상 노드의 kubelet은 파드가 해당 노드에 스케줄링된 것을 확인하자마자 파드의 컨테이너를 생성하고 실행한다.
- p490
- 노드의 선택은 그림 11.5에서 보는 것처럼 두 부분으로 나눌 수 있다.
- 모든 노드 중에서 파드를 스케줄링할 수 있는 노드 목록을 필터링한다.
- 수용 가능한 노드의 우선순위를 정하고 점수가 높은 노드를 선택한다. 만약 여러노드가 같은 최상위 점수를 가지고 있다면, 파드가 모든 노드에 고르게 배포되도록 라운드-로빈을 사용한다.
- 모든 노드 중에서 파드를 스케줄링할 수 있는 노드 목록을 필터링한다.
- 스케줄러는 미리 설정된 조건 함수 목록에 각 노드를 전달한다. 이들 함수는 다음과 같은 다양한 조건을 확인한다.
- 노드가 하드웨어 리소스에 대한 파드 요청을 충족시킬 수 있는가?
- 노드에 리소스가 부족한가
- 노드가 파드 정의 안에 있는 노드 셀렉터와 일치하는 레이블을 가지고 있는가?
- 파드가 특정 호스트 포트에 할당되도록 요청한 경우 해당 포트가 이 노드에서 이미 사용 중인가?
- 파드 요청이 특정한 유형의 볼륨을 요청하는 경우 이 노드에서 해당 볼륨을 파드에 마운트 할 수 있는가. 아니면 이 노드에 있는 다른 파드가 이미 같은 볼륨을 사용하고 있는가?
- 파드가 노드의 테인트를 허용하는가?
- 파드가 노드와 파드의 어피니티, 안티-어피니티 규칙을 지정했는가? 만약에 그렇다면 이 노드에 파드를 스케줄링하면 이런 규칙을 어기게 되는가?
- 노드가 하드웨어 리소스에 대한 파드 요청을 충족시킬 수 있는가?
- 노드의 선택은 그림 11.5에서 보는 것처럼 두 부분으로 나눌 수 있다.
- p492
- 클러스터에서 스케줄러를 하나만 실행하는 대신 여러 개의 스케줄러를 실행할 수 있다. 그런 다음에 파드 정의 안에 schedulerName 속성에 파드를 스케줄링할 때 사용할 스케줄러를 지정한다.
- 클러스터에서 스케줄러를 하나만 실행하는 대신 여러 개의 스케줄러를 실행할 수 있다. 그런 다음에 파드 정의 안에 schedulerName 속성에 파드를 스케줄링할 때 사용할 스케줄러를 지정한다.
11.1.6. 컨트롤러 매니저에서 실행되는 컨트롤러 소개 ¶
- p493
- API 서버로 배포된 리소스에 지정된 대로 시스템을 원하는 상태로 수렴되도록 하는 다른 활성 구성 요소가 필요하다. 이는 컨트롤러 매니지 안에서 실행되는 컨트롤러에 의해 수행된다.
- 컨트롤러의 목록은 다음과 같다.
- 레플리케이션 매니저
- 레플리카셋, 데몬셋, 잡 컨트롤러
- 디플로이먼트 컨트롤러
- 스테이트풀셋 컨트롤러
- 노드 컨트롤러
- 서비스 컨트롤러
- 엔드포인트 컨트롤러
- 네임스페이스 컨트롤러
- 퍼시스턴트볼륨 컨트롤러
- 그 밖의 컨트롤러
- 레플리케이션 매니저
- API 서버로 배포된 리소스에 지정된 대로 시스템을 원하는 상태로 수렴되도록 하는 다른 활성 구성 요소가 필요하다. 이는 컨트롤러 매니지 안에서 실행되는 컨트롤러에 의해 수행된다.
- p494
- 컨트롤러는 다양한 작업을 수행하지만 모두 API 서버에서 리소스가 변경되는 것을 감시하고 각 변경 작업을 수행한다.
- 컨트롤러는 다양한 작업을 수행하지만 모두 API 서버에서 리소스가 변경되는 것을 감시하고 각 변경 작업을 수행한다.
11.1.7. Kubelet이 하는 일 ¶
- p499
- Kubelet은 워커 노드에서 실행하는 모든 것을 담당하는 구성 요소다. 첫번째 작업은 Kubelet이 실행중인 노드를 노드 리소스로 만들어서 API 서버에 등록하는 것이다. 그런 다음 API 서버를 지속적으로 모니터링해 해당 노드에 파드가 스케줄링 되면, 파드의 컨테이너를 시작한다.그런 다음 실행 중인 컨테이너를 계속 모니터링하면서 상태, 이벤트, 리소스 사용량을 API 서버에 보고한다.
- Kubelet은 컨테이너 라이브니스 프로브를 실행하는 구성 요소이기도 하며, 프로브가 실패할 경우 컨테이너를 다시 시작한다. 마지막으로 API 서버에서 파드가 삭제되면 컨테이너를 정지하고 파드가 종료된 것을 서버에 통보한다.
- Kubelet은 워커 노드에서 실행하는 모든 것을 담당하는 구성 요소다. 첫번째 작업은 Kubelet이 실행중인 노드를 노드 리소스로 만들어서 API 서버에 등록하는 것이다. 그런 다음 API 서버를 지속적으로 모니터링해 해당 노드에 파드가 스케줄링 되면, 파드의 컨테이너를 시작한다.그런 다음 실행 중인 컨테이너를 계속 모니터링하면서 상태, 이벤트, 리소스 사용량을 API 서버에 보고한다.
11.1.8. 쿠버네티스 서비스 프록시의 역할 ¶
- p501
- kube-proxy는 서비스의 IP와 포인트로 들어온 접속을 서비스를 지원하는 파드 중 하나와 연결시켜준다. 서비스가 둘 이상의 파드에서 지원되는 경우 프록시는 파드 간에 로드 밸런싱을 수행한다.
- kube-proxy는 서비스의 IP와 포인트로 들어온 접속을 서비스를 지원하는 파드 중 하나와 연결시켜준다. 서비스가 둘 이상의 파드에서 지원되는 경우 프록시는 파드 간에 로드 밸런싱을 수행한다.
11.1.9. 쿠버네티스 애드온 소개 ¶
- p502
- 쿠버네티스 서비스의 DNS 조회, 여러 HTTP 서비스를 단일 외부 IP 주소로 노출하는 기능, 쿠버네티스 웹 대시보드와 같은 것들이 있다.
- 쿠버네티스 서비스의 DNS 조회, 여러 HTTP 서비스를 단일 외부 IP 주소로 노출하는 기능, 쿠버네티스 웹 대시보드와 같은 것들이 있다.
11.2. 컨트롤러가 협업하는 방법 ¶
- p505
- 전체 프로세스를 시작하기 전에도 컨트롤러와 스케줄러 그리고 kubelet은 API 서버에서 각 리소스 유형이 변경되는 것을 감시한다.
- 전체 프로세스를 시작하기 전에도 컨트롤러와 스케줄러 그리고 kubelet은 API 서버에서 각 리소스 유형이 변경되는 것을 감시한다.
- p506
- 이벤트 체인
- 디플로이먼트 리소스 생성
- 감시를 통한 통보
- 레플리카셋 생성
- 통보
- 파드 생성
- 감시를 통한 통보
- 파드를 노드에 할당
- 감시를 통한 통보
- 도커에 컨테이너 실행 요청
- 컨테이너 실행
- 디플로이먼트 리소스 생성
- 이벤트 체인
- p509
$ kubectl get events --watch
11.3. 실행 중인 파드에 관한 이해 ¶
- p511
- 이 퍼즈 컨테이너는 파드의 모든 컨테이너를 함께 담고 있는 컨테이너다. 파드의 모든 컨테이너가 동일한 네트워크와 리눅스 네임스페이스를 공유하는 방법을 기억하는가? 퍼즈 컨테이너는 이러한 네임스페이스를 모두 보유하는 게 유일한 목적인 인프라스트럭처 컨테이너다. 파드의 다른 사용자 정의 컨테이너는 파드 인프라스트럭처 컨테이너의 네임스페이스를 사용한다.
- 만약에 인프라스트럭처 컨테이너가 그 중간에 종료되면, kubelet이 인프라스트럭처와 파드의 모든 컨테이너를 다시 생성한다.
- 이 퍼즈 컨테이너는 파드의 모든 컨테이너를 함께 담고 있는 컨테이너다. 파드의 모든 컨테이너가 동일한 네트워크와 리눅스 네임스페이스를 공유하는 방법을 기억하는가? 퍼즈 컨테이너는 이러한 네임스페이스를 모두 보유하는 게 유일한 목적인 인프라스트럭처 컨테이너다. 파드의 다른 사용자 정의 컨테이너는 파드 인프라스트럭처 컨테이너의 네임스페이스를 사용한다.
11.4. 파드 간 네트워킹 ¶
- p512
- 네트워크는 쿠버네티스 자ㅔ가 아닌, 시스템 관리자 또는 컨테이너 네트워크 인터페이스 플러그인에 의해 제공된다.
- 파드 사이에 NAT가 없으면 내부에서 실행 중인 애플리케이션이 다른 파드에 자동으로 등록되도록 할 수 있따.
- 파드가 인터넷에 있는 서비스와 통신할 때는 패킷의 출발지 IP를 변경하는 것이 필요하다. 파드의 IP는 사설이기 때문이다. 외부로 나가는 패킷의 출발지 IP는 호스트 워커 노드의 IP로 변경된다.
- 네트워크는 쿠버네티스 자ㅔ가 아닌, 시스템 관리자 또는 컨테이너 네트워크 인터페이스 플러그인에 의해 제공된다.
- p514
- 노드의 파드는 가상 이더넷 인터페이스 쌍을 통해 같은 브리지로 연결된다.
- 노드의 파드는 가상 이더넷 인터페이스 쌍을 통해 같은 브리지로 연결된다.
- p516
- SDN을 이용하면 하부 네트워크 토폴로지가 아무리 복잡해지더라도 노드들이 같은 네트워크에 연결된 것으로 볼 수 있다. 파드에서 전송한 패킷은 캡슐화 돼 네트워크로 다른 파드가 실행 중인 노드로 전달되고, 디캡슐화 단계를 거쳐 원래 패킷 형태로 대상 파드에 전달된다.
- SDN을 이용하면 하부 네트워크 토폴로지가 아무리 복잡해지더라도 노드들이 같은 네트워크에 연결된 것으로 볼 수 있다. 파드에서 전송한 패킷은 캡슐화 돼 네트워크로 다른 파드가 실행 중인 노드로 전달되고, 디캡슐화 단계를 거쳐 원래 패킷 형태로 대상 파드에 전달된다.
11.5. 서비스 구현 방식 ¶
- p518
- 성능이 더 우수한 iptables 프록시 모드가 이를 대체했다.
- API 서버에서 서비스를 생성하면, 가상 IP 주소가 바로 할당된다.
- 서비스의 IP/포트 쌍으로 향하는 패킷을 가로채서, 목적지 주소를 변경해 패킷이 서비스를 지원하는 여러 파드 중 하나로 리디렉션되도록 하는 몇 개의 iptables 규칙을 설정함으로써 이뤄진다.
- 성능이 더 우수한 iptables 프록시 모드가 이를 대체했다.
11.6. 고가용성 클러스터 실행 ¶
- p520
- 애플리케이션의 가용성을 높이려면 디플로이먼트 리소스로 애플리케이션을 실행하고 적절한 수의 레플리카를 설정하기만 하면 되며, 나머지는 쿠버네티스가 처리한다.
- 가동 중단 시간을 중리기 위해서는 애플리케이션을 수평으로 확장할 수 있어야 하지만 애플리케이션이 그런 경우에 속하지 않더라도 레클리카 수가 1로 지정된 디플로이먼트를 사용해야 한다.
- 활성 복제본과 함께 비활성 복제본을 실행해두고 빠른 임대 혹은 리더 선출 매커니즘을 이용해 단 하나만 활성화 상태로 만들어야 한다.
- 애플리케이션의 가용성을 높이려면 디플로이먼트 리소스로 애플리케이션을 실행하고 적절한 수의 레플리카를 설정하기만 하면 되며, 나머지는 쿠버네티스가 처리한다.
- p522
- 쿠버네티스 가용성을 높이기 위해서는 다음 구성 요소의 여러 인스턴스를 여러 마스터 노드에서 실행해야 한다.
- etcd
- API 서버
- 컨트롤러 매니저
- 스케줄러
- etcd
- 쿠버네티스 가용성을 높이기 위해서는 다음 구성 요소의 여러 인스턴스를 여러 마스터 노드에서 실행해야 한다.
- p523
- 노드 한 대 이상으로 내결함성을 높이려면 5대 혹은 7대로 구성된 etcd 노드가 필요하다.
- 여러 APi 서버 인스턴스 실행
- API 서버의 가용성을 높이는 일은 훨씬 간단하다. API 서버는 상태를 저장하지 않기때문에 필요한 만큼 많은 API 서버를 실행할 수 있고 서로 인지할 필요도 없다.
- API 서버의 가용성을 높이는 일은 훨씬 간단하다. API 서버는 상태를 저장하지 않기때문에 필요한 만큼 많은 API 서버를 실행할 수 있고 서로 인지할 필요도 없다.
- 노드 한 대 이상으로 내결함성을 높이려면 5대 혹은 7대로 구성된 etcd 노드가 필요하다.
12.1. 인증 이해 ¶
- p528
- API 서브를 하나 이상의 인증 플러그인으로 구성할 수 있다고 했다.
- 인증 플러그인은 다음 방법을 사용해 클라이언트의 아이덴티티를 얻는다
- 클라이언트의 인증서
- HTTP 헤더로 전달된 인증 토큰
- 기본 HTTP 인증
- 기타
- 클라이언트의 인증서
- 쿠버네티스는 API 서버에 접속하는 두 종류의 클라이언트를 구분한다.
- 실제 사람(사용자)
- 파드
- 실제 사람(사용자)
- 사용자는 싱글 사인 온과 같은 외부 시스템에 의해 관리돼야 하지만 파드는 서비스 어카운트라는 매커니즘을 사용하며, 클러스터에 서비스어카운트 리소스로 생성되고 저장된다. 이와는 대조적으로 사용자 계정을 나타내는 자원은 없으며, 이는 API 서버를 통해 사용자를 생성, 업데이트 또는 삭제할 수 없다는 뜻이다.
- 인증 플러그인은 사용자 이름 및 사용자 ID와 함께 그룹을 반환한다고 말했다. 그룹은 개별 사용자에게 권한을 부여하지 않고 한 번에 여러 사용자에게 권한을 부여하는 데 사용된다.
- API 서브를 하나 이상의 인증 플러그인으로 구성할 수 있다고 했다.
- p530
$ kubectl get sa
- 각 파드는 파드의 네임스페이스에 있는 하나의 서비스어카운트와 연계된다.
- p531
- 사용 가능한 인가 플러그인 중 하는 역할 기반 액세스 제어 플러그인이다.
- 사용 가능한 인가 플러그인 중 하는 역할 기반 액세스 제어 플러그인이다.
- p532
- 리소스의 메타데이터를 검색해야 하는 파드는 해당 오브젝트의 메타데이터만 읽어야 한다. 리소스의 메타데이터를 검색해야 하는 파드는 해당 오브젝트의 메타데이터만 읽을 수 있는 서비스어카운트로 실행해야 하며, 오브젝트를 수정해야 하는 파드는 API 오브젝트를 수정할 수 있는 고유한 서비스 어카운트로 실행해야 한다.
- 리소스의 메타데이터를 검색해야 하는 파드는 해당 오브젝트의 메타데이터만 읽어야 한다. 리소스의 메타데이터를 검색해야 하는 파드는 해당 오브젝트의 메타데이터만 읽을 수 있는 서비스어카운트로 실행해야 하며, 오브젝트를 수정해야 하는 파드는 API 오브젝트를 수정할 수 있는 고유한 서비스 어카운트로 실행해야 한다.
- p532
$ kubectl create serviceaccount foo
- p534
- 서비스어카운트는 이미지 풀 시크릿 목록도 포함 할 수 있다.
- 서비스어카운트는 이미지 풀 시크릿 목록도 포함 할 수 있다.
imagepullSecrets: - name: my-dockerhub-secret
- p535
spec : serviceAccountName: foo
12.2. 역할 기반 액세스 제어로 클러스터 보안 ¶
- p537
- RBAC은 권한이 없는 사용자가 클러스터 상태를 보거나 수정하지 못하게 한다.
- RBAC은 권한이 없는 사용자가 클러스터 상태를 보거나 수정하지 못하게 한다.
- p538
- 쿠버네티스 액션에 관한 몇가지 예가 있다.
- 파드 가져오기
- 서비스 생성하기
- 시크릿 업데이트
- 기타 등등
- 파드 가져오기
- 쿠버네티스 액션에 관한 몇가지 예가 있다.
- p539
- RBAC 인가 플러그인은 사용자가 액션을 수행할 수 있는지 여부를 결정하는 핵심 요소로 사용자 롤을 사용한다. 주체는 하나 이상의 롤과 연계돼 있으며 각 롤은 특정 리소스에 특정 동사를 수행할 수 있다.
- RBAC 인가 규칙은 네 개의 리소스로 구성되며 두 개의 그룹으로 분류할 수 있다.
- 롤과 클러스터롤 : 리소스에 수행할 수 있는 동사를 지정한다.
- 롤바인딩과 클러스터롤바인딩 : 위의 롤을 특정 사용자, 그룹, 또는 서비스어카운트에 바인딩한다.
- 롤은 수행할 수 있는 작업을 정의하고, 바인딩은 누가 이를 수행할 수 있는지를 정의한다.
- 롤과 클러스터롤 : 리소스에 수행할 수 있는 동사를 지정한다.
- RBAC 인가 플러그인은 사용자가 액션을 수행할 수 있는지 여부를 결정하는 핵심 요소로 사용자 롤을 사용한다. 주체는 하나 이상의 롤과 연계돼 있으며 각 롤은 특정 리소스에 특정 동사를 수행할 수 있다.
- p540
- 롤과 클러스터롤 또는 롤바인딩과 클러스터롤 바인딩의 차이점을 롤과 롤바인딩은 네임스페이스가 지정된 리소스이고 클러스터롤과 클러스터롤바인딩은 네임스페이스를 지정하지 않는 클러스터 수준의 리소스라는 것이다.
- 롤과 클러스터롤 또는 롤바인딩과 클러스터롤 바인딩의 차이점을 롤과 롤바인딩은 네임스페이스가 지정된 리소스이고 클러스터롤과 클러스터롤바인딩은 네임스페이스를 지정하지 않는 클러스터 수준의 리소스라는 것이다.
- p552
- 클러스터 수준 리소스에는 동일한 방식을 사용할 수 없다. 클러스터 수준 리소스에 액세스 권한을 부여하려면 항상 클러스터롤바인딩을 사용해야 한다.
- 클러스터 수준 리소스에는 동일한 방식을 사용할 수 없다. 클러스터 수준 리소스에 액세스 권한을 부여하려면 항상 클러스터롤바인딩을 사용해야 한다.
- p561
- 특정 롤과 바인딩의 조합을 사용해야 하는 경우
- 클러스터 수준 리소스 = 클러스터롤 + 클러스터롤바인딩
- 리소스가 아닌 URL = 클러스터롤 + 클러스터롤바인딩
- 모든 네임스페이스의 네임스페이스로 지정된 리소스 = 클러스터롤 + 클러스터롤바인딩
- 특정 네임스페이스의 네임스페이스로 지정된 리소스 = 클러스터롤 + 롤바인딩
- 특정 네임스페이스의 네임스페이스로 지정된 리소스 = 롤 + 롤바인딩
- 클러스터 수준 리소스 = 클러스터롤 + 클러스터롤바인딩
- 특정 롤과 바인딩의 조합을 사용해야 하는 경우
- p562
- 쿠버네티스는 API 서버가 시작될 때마다 업데이트되는 클러스터롤과 클러스터롤바인딩의 디폴트 세트를 제공한다.
- 쿠버네티스는 API 서버가 시작될 때마다 업데이트되는 클러스터롤과 클러스터롤바인딩의 디폴트 세트를 제공한다.
13.1. 파드에서 호스트 노드의 네임스페이스 사용 ¶
- p568
- 각 파드는 고유한 PID 네임스페이스가 있기 때문에 고유한 프로세스 트리가 있으며 고유한 IPC 네임스페이스도 사용하므로 동일한 파드의 프로세스 간 통신 메커니즘 으로 서로 통신할 수 있다.
- 특정 파드는 호스트의 기본 네임스페이스에서 작동해야 노드의 리소스와 장치를 읽고 조작할 수 있다. 예를 들어 파드는 가상 네트워크 어댑터 대신 노드의 실제 네트워크 어댑터를 사용해야 할수도 있다. 이는 파드 스펙에서 hostNetwork 속성을 true로 설정하면 된다.
- 이는 파드 자체가 IP 주소를 갖는것이 아니라, 포트를 바인드하는 프로세스를 실행할 경우 해당 프로세스는 노드의 포트에 직접 바인드된다는 의미다.
- 각 파드는 고유한 PID 네임스페이스가 있기 때문에 고유한 프로세스 트리가 있으며 고유한 IPC 네임스페이스도 사용하므로 동일한 파드의 프로세스 간 통신 메커니즘 으로 서로 통신할 수 있다.
spec: hostNetwork: true
- p570
- 파드는 hostNetwork 옵션으로 노드의 기본 네임스페이스의 포트에 바인딩할 수 있지만 여전히 고유한 네트워크 네임스페이스를 갖는다. 이는 컨테이너의 포트를 정의하는 sepc.containers.ports 필드 안에 hostPort 속성을 사용해 할수 있다.
- hostPort는 Nodeport로 노출된 파드와 다르다. - 김준석
- hostPort는 Nodeport로 노출된 파드와 다르다. - 김준석
- 파드는 hostNetwork 옵션으로 노드의 기본 네임스페이스의 포트에 바인딩할 수 있지만 여전히 고유한 네트워크 네임스페이스를 갖는다. 이는 컨테이너의 포트를 정의하는 sepc.containers.ports 필드 안에 hostPort 속성을 사용해 할수 있다.
spec: containers: .. ports: - containerPort: 8080 hostPort: 9000 protocol: TCP
- p573
- hostNetwork 옵션과 유사한 파드 스펙 속성으로 hostPID와 hostIPC가 있다. 이를 true로 설정하면 파드의 컨테이너는 노드의 PID와 IPC 네임스페이스를 사용해 컨테이너에서 실행중인 프로세스가 노드의 다른 프로세스를 보거나 IPC로 이들과 통신할 수 있도록 한다.
- hostNetwork 옵션과 유사한 파드 스펙 속성으로 hostPID와 hostIPC가 있다. 이를 true로 설정하면 파드의 컨테이너는 노드의 PID와 IPC 네임스페이스를 사용해 컨테이너에서 실행중인 프로세스가 노드의 다른 프로세스를 보거나 IPC로 이들과 통신할 수 있도록 한다.
spec: hostPID: true hostIPC: true
13.2. 컨테이너의 보안 컨텍스트 구성 ¶
- p574
- 파드 컨텍스트 아래의 개별 컨테이너 스펙에서 직접 지정할 수 있는 securityContext 속성으로 다른 보안 관련 기능을 파드와 파드의 컨테이너에 구성할 수 있다.
- 보안 컨텍스트를 설정하면 다음과 같은 다양한 작업을 수행할 수 있다.
- 컨테이너의 프로세스를 실행할 사용자ID 지정하기
- 컨테이너가 루트로 실행되는 것 방지하기
- 컨테이너를 특권 모드에서 실행해 노드의 커널에 관한 모든 접근 권한을 가짐
- 특권 모드에서 컨테이너를 실행해 컨테이너에 가능한 모든 권한을 부여하는 것과 달리 기능을 추가하거나 삭제해 세분화된 권한 구성하기
- 컨테이너의 권한 확인을 강력하게 하기 위해 SELinux 옵션 설정하기
- 프로세스가 컨테이너의 파일시스템에 쓰기 방지하기
- 컨테이너의 프로세스를 실행할 사용자ID 지정하기
- 파드 컨텍스트 아래의 개별 컨테이너 스펙에서 직접 지정할 수 있는 securityContext 속성으로 다른 보안 관련 기능을 파드와 파드의 컨테이너에 구성할 수 있다.
- p575
$ kubectl exec pod-with-defaults id uid=0(root) gid=0(root) ...
- p576
- 컨테이너 이미지에 설정한 것과 다른 사용자 ID로 파드를 실행하려면 파드의 securityContext.reunAsUser 속성을 설정해야한다.
spec : containers: .. securityContext: runAsUser: 405
- 컨테이너 이미지에 설정한 것과 다른 사용자 ID로 파드를 실행하려면 파드의 securityContext.reunAsUser 속성을 설정해야한다.
- p577
- 대부분의 컨테이너는 호스트 시스템과 분리돼 있지만 프로세스를 루트로 실행하는 것은 여전히 나쁜 관행이다.
securityContext: runAsNonRoot: true
- 대부분의 컨테이너는 호스트 시스템과 분리돼 있지만 프로세스를 루트로 실행하는 것은 여전히 나쁜 관행이다.
- p578
securityContext: privileged: true
- 노드의 커널의 모든 액세스 권한을 얻기 위해 파드의 컨테이너는 특권 모드로 실행된다.
- p580
- 권한 있는 컨테이너를 만들고 무제한 권한을 부여하는 대신 보안 관점에서 훨씬 안전한 방법은 실제로 필요한 커널 기능만 액세스하도록 하는것이다.
securityContext: capabilities: add: - SYS_TIME
- 권한 있는 컨테이너를 만들고 무제한 권한을 부여하는 대신 보안 관점에서 훨씬 안전한 방법은 실제로 필요한 커널 기능만 액세스하도록 하는것이다.
- p582
- 컨테이너가 이를 수행하지 못하게 하려면 컨테이너의 securityContext.capabilities.drop 속성 아래에 기능을 조회해 기능을 삭제해야 한다.
securityContext: capabilities: drop: - CHown
- 컨테이너가 이를 수행하지 못하게 하려면 컨테이너의 securityContext.capabilities.drop 속성 아래에 기능을 조회해 기능을 삭제해야 한다.
- p583
- 컨테이너에서 실행 중인 프로세스가 컨테이너의 파일시스템에 쓰지 못하게 하고 마운트된 볼륨에만 쓰도록 할 수 있다.
// 파일시스템은 못쓰지만 마운트 볼륨은 씀 securityContext: readonlyRootFilesystem: true volumeMounts: - name: my-volume mountpath: /volume readOnly: false
- 컨테이너에서 실행 중인 프로세스가 컨테이너의 파일시스템에 쓰지 못하게 하고 마운트된 볼륨에만 쓰도록 할 수 있다.
- p585
- 6장에서 파드의 컨테이너 간에 데이터를 공유하는 데 볼륨을 사용하는 방법을 설명했다.
- 두 컨테이너가 모두 루트로 실행돼 볼륨의 모든 파일에 대한 전체 액세스 권한을 부여했기 때문이다.
- 쿠버네티스를 사용하면 컨테이너에서 실행 중인 모든 파드의 supplementalGroups 속성을 지정해 실행 중인 사용자 ID에 상관없이 파일을 공유할 수 있따. 이는 다음 두가지 속성을 사용해 수행된다.
- fsGroup
- supplementalGroups
- fsGroup
securityContext: fsGroup: 555 supplementalGroups: [666, 777]
- 6장에서 파드의 컨테이너 간에 데이터를 공유하는 데 볼륨을 사용하는 방법을 설명했다.
13.3. 파드의 보안 관련 기능 사용 제한 ¶
- p587
- 클러스터 관리자는 하나 이상의 PodSecurityPolicy 리소스를 생성해 앞으로 설명한 보안 관련 기능의 사용을 제한할 수 있다.
- 클러스터 관리자는 하나 이상의 PodSecurityPolicy 리소스를 생성해 앞으로 설명한 보안 관련 기능의 사용을 제한할 수 있다.
- p588
- p589
- PodSecurityPolicy 리소스는 다음을 정의한다.
- 파드가 호스트의 IPC, PID 또는 네트워크 네임스페이스를 사용할 수 있는지 여부
- 파드가 바인딩할 수 있는 포트
- 컨테이너가 실행할 수 있는 사용자 ID
- 특권을 갖는 컨테이너가 있는 파드를 만들 수 있는지 여부
- 어떤 커널 기능이 허용되는지, 어떤 기능이 기본으로 추가되거나 혹은 항상 삭제되는지 여부
- 컨테이너가 사용할 수 있는 SELinuxs 레이블
- 컨테이너가 쓰기 가능한 루트 파일시스템을 사용할 수 있는지 여부
- 컨테이너가 실행할 수 있는 파일시스템 그룹
- 파드가 사용할 수 있는 볼륨 유형
- 파드가 호스트의 IPC, PID 또는 네트워크 네임스페이스를 사용할 수 있는지 여부
- PodSecurityPolicy 리소스는 다음을 정의한다.
- p591
- 허용된 사용자 또는 그룹 ID 목록을 제한하려면 MustRunAs 규칙을 변경해 허용할 그룹 ID를 지정할 수 있다.
- 허용된 사용자 또는 그룹 ID 목록을 제한하려면 MustRunAs 규칙을 변경해 허용할 그룹 ID를 지정할 수 있다.
- p593
- runAsUser 필드의 경우 MustRunAsNonRoot라는 추가 규칙을 사용할 수 있다. 이름에서 알수 있듯이 사용자는 루트로 실행되는 컨테이너를 배포할 수 없다.
- runAsUser 필드의 경우 MustRunAsNonRoot라는 추가 규칙을 사용할 수 있다. 이름에서 알수 있듯이 사용자는 루트로 실행되는 컨테이너를 배포할 수 없다.
- p594
- 그동안 배운 대로 컨테이너는 특권 모드에서 실행될 수 있으며 각 컨테이너에 리눅스 커널 기능을 추가하거나 삭제해 좀 더 세분화된 권한 구성을 정의할 수 있다. 다음 필드 세 개는 컨테이너의 기능에 영향을 준다.
- allowedCapabilities 컨테이너에 어떤 기능을 추가할지 지정
- defaultAddCapabilities 모든 컨테이너에 기능 추가
- requiredDropCapabilities 컨테이너에서 기능 제거
- allowedCapabilities 컨테이너에 어떤 기능을 추가할지 지정
- 그동안 배운 대로 컨테이너는 특권 모드에서 실행될 수 있으며 각 컨테이너에 리눅스 커널 기능을 추가하거나 삭제해 좀 더 세분화된 권한 구성을 정의할 수 있다. 다음 필드 세 개는 컨테이너의 기능에 영향을 준다.
- p596
- p598
$ kubectl create clusterrole psp-default --verb=use --resource=podsecuritypolicies --resource-name=default $ kubectl create clusterrole psp-privileged --verb=use --resource=podsecuritypolicies --resource-name=previleged
$ kubectl create clusterrolebinding psp-all-users --clusterrole=psp-defulat --group=system:authenticated $ kubectl create clusterrolebinding psp-bob --clusterrole=psp-privileged --user=bob
13.4. 파드 네트워크 격리 ¶
- p601
- NetworkPolicy는 해당 레이블 셀렉터와 일치하는 파드에 적용되며 일치하는 파드에 액세스할 수 있는 소스나 파드에서 액세스할 수 있는 대상을 지정한다. 이것은 각각 인그레스와 이그레스 규칙으로 구성된다. 두 유형의 규칙은 파드 셀렉터와 일치하는 파드나 레이블이 네임스페이스 셀렉터와 일치하는 네임스페이스의 모든 파드, 또는 CIDR표기법을 사용해 지정된 네트워크 IP 대역과 일치하는 파드에 대해 적용된다.
- NetworkPolicy는 해당 레이블 셀렉터와 일치하는 파드에 적용되며 일치하는 파드에 액세스할 수 있는 소스나 파드에서 액세스할 수 있는 대상을 지정한다. 이것은 각각 인그레스와 이그레스 규칙으로 구성된다. 두 유형의 규칙은 파드 셀렉터와 일치하는 파드나 레이블이 네임스페이스 셀렉터와 일치하는 네임스페이스의 모든 파드, 또는 CIDR표기법을 사용해 지정된 네트워크 IP 대역과 일치하는 파드에 대해 적용된다.
- p602
kind: NetworkPolicy metadata: name: default-deny spec: podSelector: // 모두 매칭되어 모든 네트워크 deny
kind: NetworkPolicy metadata: name: postgres-netpolicy spec: podSelector: matchLabels: app: database ingress: - from: - podSelector: matchLabels: app: webserver ports: - port: 5432
ingress: - from: - namespaceSelector: matchLabels: tenant: manning ports: - port: 80
- p606
ingress: - from: - inBlock: cidr: 192.168.1.0/24
egress: - to: - podSelector: matchLabels: app: database
14.1. 파드 컨테이너의 리소스 요청 ¶
- p610
- 파드의 리소스 요청과 제한은 모든 컨테이너의 리소스 요청과 제한의 합이다.
- 파드 리소스를 컨테이너들이 나눠 쓰는 것 - 서지혜
- 200 밀리코어는 1/5 CPU
- 파드 리소스를 컨테이너들이 나눠 쓰는 것 - 서지혜
- Mi는 이진주 시반의 Mebibyte를 의미한다. MB(megabyte)는 십진수 기반으로 차이가 있다.
- 파드의 리소스 요청과 제한은 모든 컨테이너의 리소스 요청과 제한의 합이다.
- p611
- CPU 요청을 지정하지 않으면 ... 최악의 경우 CPU 시간을 전혀 할당받지 못할 수 있다.
- request 가 매우 낮을경우에도 발생합니다. 10m~50m 으로 설정했다가 1~5초 정도의 delay를 겪을수도 있습니다. - bluemir
- request 가 매우 낮을경우에도 발생합니다. 10m~50m 으로 설정했다가 1~5초 정도의 delay를 겪을수도 있습니다. - bluemir
- 요청(request)는 컨테이너가 사용할 수 있는 CPU 양을 제한하지 않으므로 이는 예견된 일이다. 제한을 하려면 CPU 제한(limits)을 지정해야 한다.
- request는 최소 할당 리소스, limits는 최대 할당 리소스 - 서지혜
- request는 최소 할당 리소스, limits는 최대 할당 리소스 - 서지혜
$ kubectl exec -it requrests-pod top
- CPU 요청을 지정하지 않으면 ... 최악의 경우 CPU 시간을 전혀 할당받지 못할 수 있다.
- p612
- 스케줄러는 파드를 스케줄링 할 때 파드의 리소스 요청 사항을 만족하는 충분한 리소스를 가진 노드만을 고려한다.
- 스케줄러는 스케줄링을 하는 시점에 각 개별 리소스가 얼마나 사용되는지 보지 않고, 노드에 배포된 파드들의 리소스 요청량의 전체 합만을 본다는 것이다.
- 실제 파드가 그보다 적게 사용하고 있어도 요청(request)들의 총 합만 고려하므로 스케줄 계산 간단해 질 듯. 그래서 가끔 요청 값을 최적화 하는 것도 필요하다 - 서지혜
- 실제 파드가 그보다 적게 사용하고 있어도 요청(request)들의 총 합만 고려하므로 스케줄 계산 간단해 질 듯. 그래서 가끔 요청 값을 최적화 하는 것도 필요하다 - 서지혜
- 스케줄러는 파드를 스케줄링 할 때 파드의 리소스 요청 사항을 만족하는 충분한 리소스를 가진 노드만을 고려한다.
- p613
- p614
- kubectl describe nodes의 출력 결과를 보면 노드의 사용 가능한 리소스가 두 세트로 표시된다. 노드의 capacity와 allocatable 리소스다. capacity는 노드의 총 리소스를 나타내고 파드에서 모두 사용 가능한 것은 아니다. 특정 리소스는 쿠버네티스와 시스템 구성 요소로 스케줄링된 것일 수 있다. 스케줄러는 오직 allocatable 리소스 양을 기준으로 결정한다.
- kubectl describe nodes의 출력 결과를 보면 노드의 사용 가능한 리소스가 두 세트로 표시된다. 노드의 capacity와 allocatable 리소스다. capacity는 노드의 총 리소스를 나타내고 파드에서 모두 사용 가능한 것은 아니다. 특정 리소스는 쿠버네티스와 시스템 구성 요소로 스케줄링된 것일 수 있다. 스케줄러는 오직 allocatable 리소스 양을 기준으로 결정한다.
- p617
- p619
- CPU 요청에 기반해 사용되지 않은 CPU시간이 컨테이너에 분배된다.
- 결국 아무도 사용하지 않는다면 사용 가능한 모든 CPU를 사용하는 것이 상식이다.
- 역시 그렇군 - 서지혜
- 역시 그렇군 - 서지혜
- 쿠버네티스를 사용하면 사용자 정의 리소스를 노드에 추가하고 파드의 리소스 요청으로 사용자 정의 리소스를 요청할 수 있다.
- 리소스 이름은 kubernetes.io 도메인으로 시작하지 않는 이상 example.org/my-resource 와 같이 무엇이든 될수 있다. 수량은 반드시 정수여야 한다. 이값은 capacity 필드에서 allocatable 필드로 자동으로 복사된다.
- 사용자 정의 리소스의 예로는 노드에 사용 가능한 GPU 단위 수가 있다.
- local disk의 용량등으로 정해서 사용할수도 있습니다. - bleumir
- local disk의 용량등으로 정해서 사용할수도 있습니다. - bleumir
- CPU 요청에 기반해 사용되지 않은 CPU시간이 컨테이너에 분배된다.
14.2. 컨테이너에 사용 가능한 리소스 제한 ¶
- p620
- CPU는 압축 가능한 리소스다. 즉, 컨테이너에서 실행 중인 프로세스에 부정적인 영향을 주지 않고 컨테이너가 사용하는 CPU 양을 조절할 수 있다. 메모리는 분명 다르다. 프로세스에 메모리가 주어지면 프로세스가 메모리를 해제하지 않는 한 가져갈 수 없다.
- 압축 가능한 리소스라는게 생소하군요 - 서지혜
- 압축 가능한 리소스라는게 생소하군요 - 서지혜
- CPU는 압축 가능한 리소스다. 즉, 컨테이너에서 실행 중인 프로세스에 부정적인 영향을 주지 않고 컨테이너가 사용하는 CPU 양을 조절할 수 있다. 메모리는 분명 다르다. 프로세스에 메모리가 주어지면 프로세스가 메모리를 해제하지 않는 한 가져갈 수 없다.
- p621
- 오작동하거나 악의적인 파드 하나가 실제 전체 노드를 사용할 수 없게 만들 수 있다.
- 리소스 모니터링이 필요한 이유 - 서지혜
- 리소스 모니터링이 필요한 이유 - 서지혜
- 리소스 요청과는 달리 리소스 제한은 노드의 할당 가능한 리소스 양으로 제한되지 않는다. 모든 파드의 리소스 제한 합계는 노드 용량의 100%를 초과할 수 있다.
- CPU 사용률은 조절되므로 컨테이너에 CPU 제한이 설정돼 있으면 프로세스는 설정된 제한보다 많은 CPU 시간을 할당받을 수 없다.
- 메모리는 CPU와는 다르다. 프로세스가 제한보다 많은 메모리를 할당받으려 시도하면 프로세스는 종료된다(컨테이너가 OOMKilled 됐다고 한다. OOM은 Out Of Memory다) 파드의 재시작 정책이 Always 또는 OnFailure로 설정된 경우 프로세스는 즉시 다시 시작하므로 종료됐음을 알아차리지 못할 수 있다.
- 오작동하거나 악의적인 파드 하나가 실제 전체 노드를 사용할 수 없게 만들 수 있다.
- p625
- top 명령은 컨테이너가 실행 중인 전체 노드의 메모리 양을 표시한다. 컨테이너에 사용 가능한 메모리의 제한을 설정하더라도 컨테이너는 이 제한을 인식하지 못한다.
- top 명령은 컨테이너가 실행 중인 전체 노드의 메모리 양을 표시한다. 컨테이너에 사용 가능한 메모리의 제한을 설정하더라도 컨테이너는 이 제한을 인식하지 못한다.
- p626
- 메모리와 마찬가지로 컨테이너는 컨테이너에 설정된 CPU 제한과 상관없이 노드의 모든 CPU를 본다.
- 여러분의 애플리케이션이 시스템에서 볼 수 있는 CPU 수에 의존하는 대신 Downward APi를 사용해 컨테이너의 CPU 제한을 전달하고 이를 사용할 수 있따. 또한 다음 파일을 읽어 cgroup 시스템에서 직접 설정된 CPU 제한을 얻을 수도 있다.
- 메모리와 마찬가지로 컨테이너는 컨테이너에 설정된 CPU 제한과 상관없이 노드의 모든 CPU를 본다.
14.3. 파드 QoS 클래스 이해 ¶
- p627
- p628
- 파드의 클래스가 Guaranteed이려면 다음 세 가지를 충족해야 한다.
- CPU와 메모리에 리소스 요청과 제한이 모두 설정돼야 한다.
- 각 컨테이너에 설정돼야 한다.
- 리소스 요청과 제한이 동일해야 한다.
- CPU와 메모리에 리소스 요청과 제한이 모두 설정돼야 한다.
- 컨테이너의 리소스 요청이 명시적으로 설정되지 않은 경우 기본적으로 리소스 제한과 동일하게 설정되므로 모든 리소스에 대한 제한을 지정하는 것으로 파드가 Guaranteed가 되기 충분하다.
- 컨테이너의 리소스 제한이 리소스 요청과 일치하지 않은 단일 컨테이너 파드와 적어도 한 개의 컨테이너가 리소스 요청을 지정했지만 리소스 제한을 설정하지 않은 모든 파드가 여기에 속한다.
- 파드의 클래스가 Guaranteed이려면 다음 세 가지를 충족해야 한다.
- p629
14.4. 네임스페이스별 파드에 대한 기본 요청과 제한 설정 ¶
- p633
- LimitRange 리소스는 컨테이너의각 리소스에 최소/최대 제한을 지정할 뿐만 아니라 리소스 요청을 명시적으로 지정하지 않은 컨테이너의 기본 리소스 요청을 지정한다.
- limitrange를 적용하면 파드의 처음 마주친 오류의 내용뿐만 아니라 파드가 거부된 모든 이유를 보여준다는 점이다.
- 네임스페이스가 다른 팀을 분리하거나, 동일 쿠버네티스 클러스터에서 실행하는 개발, QA, 스테이징, 프로덕션 파트를 분리하는 경우 각 네임스페이스에 다른 LimitRange를 사용하면 큰 파드는 특정 네임스페이스만 생성되는 반면 나머지 네임스페이스는 더 작은 파드로 제한되도록 보장한다.
- LimitRange 리소스는 컨테이너의각 리소스에 최소/최대 제한을 지정할 뿐만 아니라 리소스 요청을 명시적으로 지정하지 않은 컨테이너의 기본 리소스 요청을 지정한다.
14.5. 네임스페이스의 사용 가능한 총 리소스 제한하기 ¶
- p638
- 앞서 본것처럼 LimitRange는 개별 파드에만 적용되지만 클러스터 관리자는 네임스페이스에서 사용 가능한 총 리소스 양을 제한할 수 있는 방법이 필요하다. 이것은 리소스쿼터 오브젝트를 생성해 달성할 수 있다.
- 리소스쿼터는 네임스페이스에서 파드가 사용할 수 있는 컴퓨팅 리소스 양과 퍼시스턴트볼륨클레임이 사용할 수 있는 스토리지 양을 제한한다.
- 앞서 본것처럼 LimitRange는 개별 파드에만 적용되지만 클러스터 관리자는 네임스페이스에서 사용 가능한 총 리소스 양을 제한할 수 있는 방법이 필요하다. 이것은 리소스쿼터 오브젝트를 생성해 달성할 수 있다.
- p640
- p643
- 오브젝트 수의 쿼터는 현재 다음 오브젝트에 설정할 수 있다.
- 파드
- 레플리케이션컨트롤러
- 시크릿
- 컨피그맵
- 퍼시스턴트볼륨클레임
- 서비스, 로드밸런서 서비스와 노드포트 서비스와 같은 두 가지 유형의 서비스
- 파드
- 오브젝트 수의 쿼터는 현재 다음 오브젝트에 설정할 수 있다.
- p644
- 쿼터는 쿼터 범위로 제한될수 있다. 현재 BestEffort, NotBestEffort, Terminating, NotTerminating의 네 가지 범위를 사용할 수 있다.
- BestEffort 및 NotBestEffort 범위는 쿼터가 BestEffort QoS클래스 또는 다른 두 클래스 중 하나 가 있는 파드에 적용되는지 여부를 결정한다.
- Terminating과 NotTerminating은 이름에서 알수 있듯이 종료 과정의 파드에는 적용되지 않는다. 각 파드가 종료되고 실패로 표시되기 전에 얼마나 오래 실행할 수 있는지 지정할 수 있다. 파드 스펙의 activeDeadlineSeconds필드를 설정하면 된다. 이 속성은 파드가 실패로 표시된 후 종료되기 전 시작 시간을 기준으로 노드에서 활성화되도록 허용하는 시간을 정의한다. Terminating 쿼터 범위는 activeDeadLineSeconds가 설정된 파드에 적용되는 반면 NotTerminating은 그렇지 않은 파드에 적용된다.
- 쿼터는 쿼터 범위로 제한될수 있다. 현재 BestEffort, NotBestEffort, Terminating, NotTerminating의 네 가지 범위를 사용할 수 있다.
15. 파드와 클러스터 노드의 오토스케일링 ¶
- p655
- 파드에서 실행되는 애플리케이션은 레플리케이션컨트롤러, 레플리카셋, 디플로이먼트 또는 기타 확장 가능한 리소스 안에 있는 replicas 필드 값을 늘려 수동으로 확장할 수 있다.
- 쿠버네티스는 파드를 모니터링하다가 CPU 사용량이나 다른 메타륵이 증가하는 것을 감지하는 즉시 자동으로 확장할 수 있다.
- 파드에서 실행되는 애플리케이션은 레플리케이션컨트롤러, 레플리카셋, 디플로이먼트 또는 기타 확장 가능한 리소스 안에 있는 replicas 필드 값을 늘려 수동으로 확장할 수 있다.
15.1. 수평적 파드 오토스케일링 ¶
- p656
- 수평적 파드 오토스케일링은 컨트롤러가 관리 파드의 레플리카 수를 자동으로 조정하는것을 말한다.
- 이것은 Horizontal 컨트롤러에 의해 수행되며, HorizontalPodAutoscaler(HPA) 리소스를 작성해 활성화시키고 원하는 대로 설정한다.
- 컨트롤러는 주기적으로 파드 메트릭을 확인해, HorizontalPodAutoscaler 리소스에 설정돼 있는 대상 메트릭 값을 만족하는 레플리카 수를 계산한다.
- 그리고 대상 리소스 안에 있는 replicas 필드 값을 조절한다.
- 오토스케일링 프로세스는 세 단계로 나눌 수 있다.
- 확장 가능한 리소스 오브젝트에서 관리하는 모든 파드의 메트릭을 가져온다.
- 메트릭을 지정한 목표 값과 같거나 가깝도록 하기 위해 필요한 파드 수를 계산한다.
- 확장 가능한 리소스의 replicas 필드를 갱신한다.
- 확장 가능한 리소스 오브젝트에서 관리하는 모든 파드의 메트릭을 가져온다.
- 파드와 노드 메트릭은 모든 노드에서 실행되는 kubelet에서 실행되는 cAdvisor 에이전트에 의해 수집된다.
- 수평적 파드 오토스케일링은 컨트롤러가 관리 파드의 레플리카 수를 자동으로 조정하는것을 말한다.
- p658
- 오토스케일러의 스케일링 대상이 되는 리소스에 속해 있는 파드의 모든 메트릭을 가지고 있으면, 이 메트릭을 사용해 필요한 레플리카 수를 파악할 수 있다. 모든 레플리카에서 메트릭의 평균 값을 이용해 지정한 목표값과 가능한 가깝게 하는 숫자를 찾아야 한다. 이 계산의 입력은 파드 메트릭 세트이고, 출력은 하나의 정수이다.
- 오토스케일링이 여러 파드 메트릭(CPU 사용량, 초당 질의수(QPS))을 기반으로 하는 경우 계산이 그렇게 복잡하지는 않다. 오토스케일러는 각 메트릭의 레플리카 수를 개별적으로 계산한 뒤 가장 높은 값을 취한다.
- 오토스케일러의 스케일링 대상이 되는 리소스에 속해 있는 파드의 모든 메트릭을 가지고 있으면, 이 메트릭을 사용해 필요한 레플리카 수를 파악할 수 있다. 모든 레플리카에서 메트릭의 평균 값을 이용해 지정한 목표값과 가능한 가깝게 하는 숫자를 찾아야 한다. 이 계산의 입력은 파드 메트릭 세트이고, 출력은 하나의 정수이다.
- p659
- 오토스케일링 자겁의 마지막 단계는 스케일링된 리소스 오브젝트의 레플리카 개수 필드를 원하는 값으로 갱신해, 레플리카셋 컨트롤러가 추가 파드를 시작하거나 초과한 파드를 삭제하도록 하는 것이다.
- API 서버가 스케일 서브 리소스를 노출하는 한, 오토스케일러는 모든 확장 가능한 리소스를 대상으로 동작할 수 있다. 현재 노출되는 리소스는 다음과 같다.
- 디플로이먼트
- 레플리카셋
- 레플리케이션컨트롤러
- 스테이트풀셋
- 디플로이먼트
- 오토스케일링 자겁의 마지막 단계는 스케일링된 리소스 오브젝트의 레플리카 개수 필드를 원하는 값으로 갱신해, 레플리카셋 컨트롤러가 추가 파드를 시작하거나 초과한 파드를 삭제하도록 하는 것이다.
- p660
- CPU 사용률 기반 스케일링
- CPU 사용량이 100%에 도달하면 더 이상 요구에 대응할 수 없어 스케일 업(수직적 스케일링: 파드가 사용하는 CPU 양 증가)이나 스케일 아웃(수평적 스케일링: 파드 수 증가)이 필요하다. 여기서 우리는 수평적 파드 오토스케일러만 얘기하고 있기 때문에, 스케일 아웃에 관해서만 집중해보자. 스케일 아웃이 이루어지면 평균 CPU 사용량은 줄어들 것이다.
- 오토스케일러는 파드의 실제 CPU 사용량과 CPU 요청을 비교하는데, 이는 오토스케일링이 필요한 파드는 오토스케일러가 CPU 사용률을 결정하기 위해서 오토스케일링이 필요한 파드는 직접 또는 간접적으로 LimitRange 오브젝트를 통해 CPU 요청을 설정해야 한다는 것을 의미한다.
- CPU 사용률 기반 스케일링
- p662
$ kubectl autoscale deployment kubia --cpu-percent=30 --min=1 --max=5 // cpu 사용률 30% 유지 최소 1 최대 5
- p664
$ kubectl get hpa
- p668
- 오토스케일러가 어떻게 네 개의 레플리카가 필요하다는 결론을 얻었는지 살펴보자. 처음에는 레플리카 한 개가 요청을 처리하면서 CPU 사용량이 108%로 급증했다. 108을 30으로 나누면 3.6을 얻게 되는ㄴ데, 오토스케일러는 이 값을 반올림해서 4로 만든다. 108을 4로 나누면 27%를 얻는다. 만약 오토스케일러가 네 개의 파드로 스케일 업하면, 파드들의 평균 CPU 사용률은 27% 근처일 것으로 예상되고, 이 값은 목표 값이 30%에 가깝고 관찰된 CPU 사용률과 거의 비슷하다.
- 한 번의 확장 단계에서 추가할 수 있는 레플리카의 수는 제한돼 있기 때문이다. 오토스케일러는 두 개를 초과하는 레플리카가 존재할 경우 한 번의 수행에서 최대 두 배의 레플리카를 생성할 수 있다.
- 오토스케일러가 어떻게 네 개의 레플리카가 필요하다는 결론을 얻었는지 살펴보자. 처음에는 레플리카 한 개가 요청을 처리하면서 CPU 사용량이 108%로 급증했다. 108을 30으로 나누면 3.6을 얻게 되는ㄴ데, 오토스케일러는 이 값을 반올림해서 4로 만든다. 108을 4로 나누면 27%를 얻는다. 만약 오토스케일러가 네 개의 파드로 스케일 업하면, 파드들의 평균 CPU 사용률은 27% 근처일 것으로 예상되고, 이 값은 목표 값이 30%에 가깝고 관찰된 CPU 사용률과 거의 비슷하다.
- p669
- 메모리 기반 오토스케일링은 CPU 기반 오토스케일링에 비해 훨씬 문제가 많다. 가장 큰 이유는 스케일 업 후에 오래된 파드는 어떻게든 메모리를 해제하는 것이 필요하기 때문이다.
- 메모리 기반 오토스케일링은 CPU 기반 오토스케일링에 비해 훨씬 문제가 많다. 가장 큰 이유는 스케일 업 후에 오래된 파드는 어떻게든 메모리를 해제하는 것이 필요하기 때문이다.
- p670
- 쿠버네티스 오토스케일링 SIG 는 오토스케일러를 완전히 다시 설계했다.
- 쿠버네티스 오토스케일링 SIG 는 오토스케일러를 완전히 다시 설계했다.
- p671
- HPA 오브젝트에는 사용할 수 있는 세 가지 유형의 메트릭이 있다.
- 리소스
- 파드
- 오브젝트
- 리소스
- 메트릭의 예로는 이미 언급했던 초당 질의 수 또는 메시지 브로커의 큐 메시지 수 등이 있다.
- HPA 오브젝트에는 사용할 수 있는 세 가지 유형의 메트릭이 있다.
- p672
- Object 메트릭 유형은 오토스케일러가 파드를 확장할 때 파드에 직접 관련되지 않는 메트릭을 기반으로 하도록 만든다. 예를 들어 파드를 확장할 때 인그레스 오브젝트 같은 클러스터 오브젝트 메트릭을 이용할 수 있다.
- Object 메트릭 유형은 오토스케일러가 파드를 확장할 때 파드에 직접 관련되지 않는 메트릭을 기반으로 하도록 만든다. 예를 들어 파드를 확장할 때 인그레스 오브젝트 같은 클러스터 오브젝트 메트릭을 이용할 수 있다.
- p673
- 앞에서 언급한 것처럼 파드에 있는 컨테이너의 메모리 소비량은 오토스케일링에 적합한 메트릭이 아니다. 레플리카 수를 늘려도 관찰 중인 메트릭의 평균 값이 선형적으로 감소하지 않거나 최소한 선형에 가깝게 줄어들지 않는다면 오토스케일러가 제대로 동작하지 않는다.
- 오토스케일러 애플리케이션 정의 메트릭을 오토스케일러의 기반 항목으로 하기 전에, 파드 수가 증가하고 감소할 때 메트릭 값이 어떻게 변화하는지 고려해야 한다.
- 수평적 파드 오토스케일러는 현재 minReplicas 필드를 0으로 설정할 수 없기 때문에, 파드가 아무것도 하지 않더라고 오토스케일러는 파드 수를 0으로 감소시키지 않는다. 파드수를 0으로 축소할 수 있게 만들면 하드웨어 사용률이 크게 높아질 수 있따.
- 앞에서 언급한 것처럼 파드에 있는 컨테이너의 메모리 소비량은 오토스케일링에 적합한 메트릭이 아니다. 레플리카 수를 늘려도 관찰 중인 메트릭의 평균 값이 선형적으로 감소하지 않거나 최소한 선형에 가깝게 줄어들지 않는다면 오토스케일러가 제대로 동작하지 않는다.
15.2. 수직적 파드 오토스케일링 ¶
- 수평적 확장이 불가능한 애플리케이션의 경우 유일한 옵션은 수직적(더 많은 CPU와 메모리)으로 확장하는 것이다.
- 안타깝게도 집필을 마친 지금도 수직적 파드 오토스케일링은 여전히 사용할 수 없다.
15.3. 수평적 클러스터 노드 확장 ¶
- 모든 노드가 한계에 도달해 더 이상 파드를 추가할 수 없을 때는 어떻게 될까?
- 쿠버네티스는 추가적인 노드가 필요한 것을 탐지하면 가능한 빠르게 추가 노드를 클라우드 제공자에게 요청하는 기능을 가지고 있다.
- 실제로는
cloud provider
라는 componemet 에게 위임합니다. 잘 알려진 제공자(GCP, AWS)가 아닌경우 cloud provider 를 직접 구현해야 해요 - bluemir
- 실제로는
- 새 파드가 생성된 후 스케줄러가 기존 노드에 스케줄링할 수 없는 경우, 새로운 노드가 공급된다. 클러스터 오토스케일러는 이런 파드를 찾고 클라우드 제공자에 추가 노드를 시작하도록 요청한다.
- 클러스터 오토스케일러는 사용 가능한 노드 그룹을 검사해 최소한 하나의 노드 유형이 스케줄링되지 않은 파드를 수용할 수 있는지 확인한다.
- 클러스터 오토스케일러가 기존 노드에 스케일링할 수 없는 파드를 찾았을 때 스케일 업을 수행한다
- 오토스케일러가 기존 노드에 스케줄할 수 없는 파드를 발견한다.
- 오토스케일러가 어떤 노드 유형이 파드에 맞을지 결정한다. 여러 유형이 가능하다면 그중 하나를 선택한다.
- 오토스케일러가 앞에서 선택한 노드 그룹을 스케일 업한다.
- 오토스케일러가 기존 노드에 스케줄할 수 없는 파드를 발견한다.
- 오토스케일러는 모든 노드에 요청된 CPU와 메모리를 모니터링해 이를 수행한다. 특정 노드에서 실행 중인 모든 파드의 CPU와 메모리 요청이 50% 미만이면 해당 노드는 필요하지 않은 것으로 간주한다. 이것이 노드를 중단하는 데 사용하는 유일한 결정 요인은 아니다. 오토스케일러는 해당 노드에서만 실행 중인 시스템 파드가 있는지 검사한다.
- 만약 시스템 파드가 노드에서 실행 중이라면 해당 노드는 종료될 수 없다. 관리되지 않는 파드나 로컬 저장소를 가진 파드가 실행되는 경우에도 마찬가지다. 만약 시스템 파드가 노드에서 실행 중이라면 해당 노드는 종료될 수 없다. 관리되지 않는 파드나 로컬 저장소를 가진 파드가 실행되는 경우에도 마찬가지다. 파드가 제공하는 서비스가 중단될 수 있기 때문이다.
- 종료할 조드를 선택되면, 해당 노드는 먼저 스케줄링할 수 없다는 표시를 하고 노드에서 실행 중인 모든 파드를 제거한다. 제거하는 모든 노드는 레플리카셋이나 다른 컨트롤러에 속해 있기 때문에, 교체할 파드가 생성되고 남아 있는 나머지 노드에 스케줄링된다.
$ kubectl cordon <node> // 명령은 노드를 스케줄링할 수 없음으로 표시함 $ kubectl drain <node> // 명령은 노드를 스케줄링 할 수 없음으로 표시하고 노드에서 실행 중인 모든 파드를 종료한다.
- 클러스터 오토스케일러는 다음 클라우드 제공자에서 사용할 수 있다.
- 구글 쿠버네티스 엔진
- 구글 컴퓨트 엔진
- 아마존 웹 서비스
- 마이크로소프트 애저
- 구글 쿠버네티스 엔진
- p679
- 특정 서비스에서는 최소 개수의 파드가 항상 실행돼야 한다. 이는 쿼럼 기반 클러스터 애플리케이션인 경우 특히 그렇다. 이런 이유로 쿠버네티스는 스케일 다운 드으이 작업을 수행할 경우에도 유지돼야 하는 최소 파드 개수를 지정하는 방법을 제공한다.
- 특정 서비스에서는 최소 개수의 파드가 항상 실행돼야 한다. 이는 쿼럼 기반 클러스터 애플리케이션인 경우 특히 그렇다. 이런 이유로 쿠버네티스는 스케일 다운 드으이 작업을 수행할 경우에도 유지돼야 하는 최소 파드 개수를 지정하는 방법을 제공한다.
16.1. 테인트와 톨러레이션을 사용해 특정 노드에서 파드 실행 제한 ¶
- p684
- 노드 테인트와 이 테인트에 대한 파드 톨러레이션이다. 테인트와 톨러레이션은 어떤 파드가 특정 노드를 사용할 수 있는지를 제한하고자 사용된다. 노드의 테인트가 허영된 경우에만 파드가 노드세 스케줄링 될 수 있다.
- 노드 셀렉터와 노드 어피니티를 사용하는 것과는 약간 다르다.
- 노드에 테인트를 추가하는 것만으로도 파드가 특정 노드에 배포되지 않도록 한다. 테인트된 노드에 배포할 파드는 테인트된 노드를 사용하게 선택할 필요가 있는 반면, 노드 셀렉터를 사용하면 파드를 배포할 노드를 명시적으로 지정한다.
- 노드 테인트와 이 테인트에 대한 파드 톨러레이션이다. 테인트와 톨러레이션은 어떤 파드가 특정 노드를 사용할 수 있는지를 제한하고자 사용된다. 노드의 테인트가 허영된 경우에만 파드가 노드세 스케줄링 될 수 있다.
- p685
- 마스터 노드에는 테인트가 하나 있따. 테인트에는 키, 값, 효과 가 있고 <key>=<value>:<effect> 형태로 표시된다.
node-role.kubernetes.io/master <key> null <value> 효과는 NoSchedule
- 시스템 파드는 톨러레이션과 노드의 테인트가 일치하기 때문에 마스터 노드에 스케줄링 된다.
- 마스터 노드에는 테인트가 하나 있따. 테인트에는 키, 값, 효과 가 있고 <key>=<value>:<effect> 형태로 표시된다.
- p686
- 테인트 효과 이해하기
- kube-proxy 파드의 다른 두 가지 톨러레이션은 준비되지 않았거나 도달할 수 없는 노드에서 파드를 얼마나 오래 실행할 수 있는지를 정의한다.
- NoSchedule: 파드가 테인트를 허용하지 않는 경우 파드가 노드에 스케줄링되지 않는다.
- PreferNoSchedule: NoSchedule의 소프트한 버전이다. 즉, 스케줄러가 파드를 노드에 스케줄링하지 않으려 하지만 다른 곳에 스케줄링 할 수 없으면 해당 노드에 스케줄링 된다.
- NoExecuete: 스케줄링에만 영향을 주는 NoSchedule이나 PreferNoSchedule과 달리, NoExecute는 노드에서 이미 실행 중인 파드에도 영향을 준다. NoExecute 테인트를 노드에 추가하면 해당 노드에서 이미 실행 중이지만 NoExecute 테인트를 허용하지 않는 파드는 노드에서 제거된다.
- NoSchedule: 파드가 테인트를 허용하지 않는 경우 파드가 노드에 스케줄링되지 않는다.
- 테인트 효과 이해하기
- 노드에 사용자 정의 테인트 추가하기
$ kubectl taint node node1.k8s node-type=production:NoSchedule
- 파드에 톨러레이션 추가
spec: tolerations: - key: node-type Operator: Equal value: production effect: NoSchedule
- p689
- 테인트는 키와 효과만 갖고 있고, 값을 꼭 필요로 하지 않는다. 톨러레이션은 Equal 연산자를 지정해 특정한 값을 허용하거나, Exists 연산자를 사용해 특정 테인트 키에 여러값을 허용할 수 있다.
- 테인트는 키와 효과만 갖고 있고, 값을 꼭 필요로 하지 않는다. 톨러레이션은 Equal 연산자를 지정해 특정한 값을 허용하거나, Exists 연산자를 사용해 특정 테인트 키에 여러값을 허용할 수 있다.
16.2. 노드 어피니티를 사용해 파드를 특정 노드로 유인하기 ¶
- p691
- 노드 셀렉터와 유사하게 각 파드는 고유한 노드 어피니티 규칙을 정의할 수 있다. 이를 통해 꼭 지켜야 하는 필수 요구 사항이나 선호도를 지정할 수 있다.
- 노드 셀렉터와 유사하게 각 파드는 고유한 노드 어피니티 규칙을 정의할 수 있다. 이를 통해 꼭 지켜야 하는 필수 요구 사항이나 선호도를 지정할 수 있다.
- p693
apiVersion: v1 kind: Pod metadata: name: kubia-gpu spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: gpu operator: In values: - "true" containers: - image: luksa/kubia name: kubia
- requireDuringScheduleing... 이 필드 아래에 정의된 규칙은 파드가 노드로 스케줄링되고자 가져야 하는 레이블을 지정한다.
- ...IgnoredDuringExecution 이 필드 아래에 정의된 규칙은 노드에서 이미 실행중인 파드에는 영향을 미치지 않는다.
- 현재 시점에는 어피니티가 파드 스케줄링에만 영향을 미치며, 파드가 노드에서 제거되지 않음을 알려주고싶다.
- nodeSelectorTerms 필드와 matchExpressions 필드가 파드를 노드에 스케줄링하고자 노드의 레이블이 일치하도록 표현식을 정의하는데 사용된다는 것을 쉽게 이해할 수 있을 것이다.
- p695
- 새로 도입된 노드 어피니티 기능의 가장 큰 장점을 특정 파드를 스케줄링할 때 스케줄러가 선호할 노드를 지정할 수 있다는 것이다. 이는 prefereedDuringSchedulingIgnoredDuringExecution 필드를 통해 수행된다.
- 새로 도입된 노드 어피니티 기능의 가장 큰 장점을 특정 파드를 스케줄링할 때 스케줄러가 선호할 노드를 지정할 수 있다는 것이다. 이는 prefereedDuringSchedulingIgnoredDuringExecution 필드를 통해 수행된다.
- p697
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: pref spec: replicas: 5 template: metadata: labels: app: pref spec: affinity: nodeAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 80 preference: matchExpressions: - key: availability-zone operator: In values: - zone1 - weight: 20 preference: matchExpressions: - key: share-type operator: In values: - dedicated ...
- 이 파드는 어느 노드에나 스케줄링 될 수 있지만 파드의 레이블에 따라 특정 노드를 선호한다.
- p699
- 생성된 다섯 개의 파드 중 네 개는 node1에 배포됐으나 하나는 node2에 배포됐다. 왜 파드 중 하나가 node1 대신 node2에 배포돼쓸까? 그 이유는 스케줄러가 파드를 스케줄링 할 위치를 결정하는 데 노드의 어피니티 우선순위 지정 기능 외에도 다른 우선순위 지정기능을 사용하기 때문이다. 그중 하나다 Selector-spreadPriority 기능이다. 이 기능은 동일한 레플리카셋 또는 서비스에 속하는 파드를 여러 노드에 분산시켜 노드 장애로 인해 전체 서비스가 중단되지 않도록 한다. 이는 파드 중 하나가 node2에 스케줄링된 원인일 가능성이 높다.
- 생성된 다섯 개의 파드 중 네 개는 node1에 배포됐으나 하나는 node2에 배포됐다. 왜 파드 중 하나가 node1 대신 node2에 배포돼쓸까? 그 이유는 스케줄러가 파드를 스케줄링 할 위치를 결정하는 데 노드의 어피니티 우선순위 지정 기능 외에도 다른 우선순위 지정기능을 사용하기 때문이다. 그중 하나다 Selector-spreadPriority 기능이다. 이 기능은 동일한 레플리카셋 또는 서비스에 속하는 파드를 여러 노드에 분산시켜 노드 장애로 인해 전체 서비스가 중단되지 않도록 한다. 이는 파드 중 하나가 node2에 스케줄링된 원인일 가능성이 높다.
16.3. 파드 어피니티와 안티-어피니티를 이용해 파드 함께 배치하기 ¶
- p699
- 쿠버네티스가 프론트엔드 파드와 백엔드 파드를 서로 가깝게 유지하면서 적절한 곳에 배포하도록 하는 게 낫다. 이는 파드 어피니티를 사용해 달성할 수 있다.
- 쿠버네티스가 프론트엔드 파드와 백엔드 파드를 서로 가깝게 유지하면서 적절한 곳에 배포하도록 하는 게 낫다. 이는 파드 어피니티를 사용해 달성할 수 있다.
- p700
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: frontend spec: replicas: 5 template: metadata: labels: app: frontend spec: affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - topologyKey: kubernetes.io/hostname labelSelector: matchLabels: app: frontend
- 예제는 이 디플로이먼트에서 app=backend 레이블이 있는 파드와 동일한 노드/topology에 배포되도록 하는 필수 요구 사항을 갖는 파드를 생성하는 것을 보여준다.
- 백엔드 파드를 스케줄링 하는 과정에서 파드 간의 어피니티로 인해 node2가 node1보다 높은 점수를 받았다는 것을 알 수 있다.
- p703
- 노드 선호도를 지정해 스케줄러가 특정 노드에 파드를 스케줄링하도록 지시하되 해당 노드가 어떤 이유로든 파드에 맞지 않을 경우 다른 곳으로 스케줄링되게 할 수 있다.
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: frontend spec: replicas: 5 template: metadata: labels: app: frontend spec: affinity: podAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 80 podAffinityTerm: topologyKey: kubernetes.io/hostname labelSelector: matchLabels: app: backend
- 노드 선호도를 지정해 스케줄러가 특정 노드에 파드를 스케줄링하도록 지시하되 해당 노드가 어떤 이유로든 파드에 맞지 않을 경우 다른 곳으로 스케줄링되게 할 수 있다.
- p707
- 파드를 서로 멀리 떨어뜨려 놓고 싶을 수 있다. 이것을 파드 안티어피니티 podAntiAffinity 라고 한다.
- 두개의 파드 세트가 동일한 노드에서 실행되는 경우 서로의 성능을 방해하는 경우 이 기능을 사용한다.
piVersion: extensions/v1beta1 kind: Deployment metadata: name: frontend spec: replicas: 5 template: metadata: labels: app: frontend spec: affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - topologyKey: kubernetes.io/hostname labelSelector: matchLabels: app: frontend ...
- 파드를 서로 멀리 떨어뜨려 놓고 싶을 수 있다. 이것을 파드 안티어피니티 podAntiAffinity 라고 한다.