23.06.15
DEVOTEE를 활성화 시키면
지금 작성한 커뮤니티 글에 대해 1개의 댓글을 달아줍니다.
버튼을 누르면 글 수정 시 ChatGPT가 작성한 댓글이 수정됩니다.
| 컨텐츠 유형 | 제목 | 저장일 | 삭제 |
|---|
본인인증 로그인에 실패하였습니다.
회원이 아니시거나 본인인증 등록이
완료되지 않은 사용자입니다.
오늘은 2번째 쿠버네티스 101 스터디가 있는 날입니다.
1명만 업무로 바뻐서 못오셨고 9명 모두 다 모였습니다. ^^
역시 소규모로 해야 스터디가 잘 운영되네요~
오늘 주제는 다음과 같습니다.
101 참석자: 최진영, 이재규, 안승규, 이금춘, 장병진, 이석원
모니터링 참석자: 육용수, 이재상, 김예준
2회 발표자 - 이금춘
Concepts >> Containers
https://kubernetes.io/docs/concepts/containers/
Concepts >> Cluster Architecture >> Controllers
https://kubernetes.io/docs/concepts/architecture/controller/
Concepts >> Overview >> Working with Kubernetes Objects >> Labels and Selectors
https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/
Concepts >> Services, Load Balancing, and Networking
https://kubernetes.io/docs/concepts/services-networking/
Tutorials >> Learn Kubernetes Basic >> Explore Your App
https://kubernetes.io/docs/tutorials/kubernetes-basics/explore/
Tutorials >> Learn Kubernetes Basic >> Expose Your App Publicly
https://kubernetes.io/docs/tutorials/kubernetes-basics/expose/
Tutorials >> Learn Kubernetes Basic >> Scale Your App
https://kubernetes.io/docs/tutorials/kubernetes-basics/scale/
Tutorials >> Learn Kubernetes Basic >> Update Your App
https://kubernetes.io/docs/tutorials/kubernetes-basics/update/
오늘 발표는 이금춘님께서 진행해 주셨습니다.
간단한 저녁식사는 역시 데보션에서 지원했습니다. 짱짱짱!!!
https://kubernetes.io/docs/concepts/containers/
Container
전통적인 방식 - 물리서버, OS, Application 포트를 다르게 해서 실행
Virtual Machines 방식 - 물리서버위에 VM 을 띄우고 그 내부에 OS 과 어플리케이션을 설치하는 개념
Container 방식 - 물리서버 > OS > Container Runtime (Docker?) > Container
정리
컨테이너 이미지는 애플리케이션과 모든 소프트웨어 의존성을 캡슐화하는 바이너리 데이터를 나타낸다.
컨테이너 이미지는 독립적으로 실행할 수 있고 런타임 환경에 대해 잘 정의된 가정을 만드는 실행 가능한 소프트웨어 번들이다.
https://kubernetes.io/ko/docs/concepts/containers/images/
이미지 이름
컨테이너 이미지는 일반적으로 pause, example/mycontainer 또는 kube-apiserver 와 같은 이름을 부여한다. 이미지는 또한 레지스트리 호스트 이름을 포함할 수 있다. 예를 들어 fictional.registry.example/imagename 와 같다. 그리고 fictional.registry.example:10443/imagename 와 같이 포트 번호도 포함할 수 있다.
이미지 풀(pull) 정책
IfNotPresent
이미지가 로컬에 없는 경우에만 내려받는다.
Always
kubelet이 컨테이너를 기동할 때마다, kubelet이 컨테이너 이미지 레지스트리에 이름과 이미지의 다이제스트가 있는지 질의한다.
Never
kubelet은 이미지를 가져오려고 시도하지 않는다.
😀 프로덕션 환경에서 컨테이너를 배포하는 경우 :latest 태그 사용을 지양
😵💫 이미지풀백오프(ImagePullBackOff)
😵💫 런타임클래스(RuntimeClass)
😵💫 프라이빗 레지스트리에 인증하도록 노드 구성
https://kubernetes.io/ko/docs/concepts/containers/runtime-class/
런타임클래스는 컨테이너 런타임을 구성을 선택하는 기능이다. 컨테이너 런타임 구성은 파드의 컨테이너를 실행하는 데 사용된다.
동기
서로 다른 파드간에 런타임클래스를 설정하여 성능과 보안의 균형을 유지할 수 있다.
예를 들어, 일부 작업에서 높은 수준의 정보 보안 보증이 요구되는 경우, 하드웨어 가상화를 이용하는 컨테이너 런타임으로 파드를 실행하도록 예약하는 선택을 할 수 있다.
그러면 몇가지 추가적인 오버헤드는 있지만 대체 런타임을 추가 분리하는 유익이 있다.
또한 런타임클래스를 사용하여 컨테이너 런타임이 같으나 설정이 다른 여러 파드를 실행할 수 있다.
셋업
사용
스케쥴
RuntimeClass에 scheduling 필드를 지정하면, 이 RuntimeClass로 실행되는 파드가 이를 지원하는 노드로 예약되도록 제약 조건을 설정할 수 있다.
scheduling 이 설정되지 않은 경우 이 RuntimeClass는 모든 노드에서 지원되는 것으로 간주된다.
https://kubernetes.io/ko/docs/concepts/containers/container-environment/
컨테이너 환경
쿠버네티스 컨테이너 환경은 컨테이너에 몇 가지 중요한 리소스를 제공한다.
컨테이너 정보
파드 이름과 네임스페이스는 다운워드(Downward) API 를 통해 환경 변수로 구할 수 있다.
클러스터 정보
https://kubernetes.io/ko/docs/concepts/containers/container-lifecycle-hooks/
이 페이지는 kubelet이 관리하는 컨테이너가 관리 라이프사이클 동안의 이벤트에 의해 발동되는 코드를 실행하기 위해서 컨테이너 라이프사이클 훅 프레임워크를 사용하는 방법에 대해서 설명한다.
컨테이너 상태
https://kubernetes.io/ko/docs/concepts/workloads/pods/pod-lifecycle/#컨테이너-상태
전체 파드의 단계뿐 아니라, 쿠버네티스는 파드 내부의 각 컨테이너 상태를 추적한다.
컨테이너 라이프사이클 훅(hook)을 사용하여 컨테이너 라이프사이클의 특정 지점에서 실행할 이벤트를 트리거할 수 있다.
**Waiting :**만약 컨테이너가 Running 또는 Terminated 상태가 아니면, Waiting 상태이다.
Running :Running 상태는 컨테이너가 문제없이 실행되고 있음을 나타낸다. postStart 훅이 구성되어 있었다면, 이미 실행되고 완료되었다.
Terminated :Terminated 상태의 컨테이너는 실행을 시작한 다음 완료될 때까지 실행되었거나 어떤 이유로 실패했다.
kubectl 을 사용하여 컨테이너가 Terminated 인 파드를 쿼리하면, 이유와 종료 코드 그리고 해당 컨테이너의 실행 기간에 대한 시작과 종료 시간이 표시된다.
컨테이너에 구성된 preStop 훅이 있는 경우, 이 혹은 컨테이너가 Terminated 상태에 들어가기 전에 실행된다.
컨테이너 훅
PostStart : 이 훅은 컨테이너가 생성된 직후에 실행된다. 그러나 훅이 컨테이너 엔트리포인트에 앞서서 실행된다는 보장은 없다.
PreStop : 이 훅은 API 요청이나 활성 프로브(liveness probe) 실패, 선점, 자원 경합 등의 관리 이벤트로 인해 컨테이너가 종료되기 직전에 호출된다.
훅 핸들러 구현
훅 핸들러 실행
https://kubernetes.io/docs/tasks/configure-pod-container/attach-handler-lifecycle-event/
kubectl apply -f <https://k8s.io/examples/pods/lifecycle-events.yaml>
kubectl get pod lifecycle-demo
kubectl exec -it lifecycle-demo -- /bin/bash
# In your shell, verify that the postStart handler created the message file:
root@lifecycle-demo:/# cat /usr/share/message
Hello from the postStart handler🤕 훅 전달 보장
훅 전달은 한 번 이상 으로 의도되어 있는데, 이는 PostStart 또는 PreStop와 같은 특정 이벤트에 대해서, 훅이 여러 번 호출될 수 있다는 것을 의미한다. 이것을 올바르게 처리하는 것은 훅의 구현에 달려 있다.
일반적으로, 전달은 단 한 번만 이루어진다. 예를 들어, HTTP 훅 수신기가 다운되어 트래픽을 받을 수 없는 경우에도, 재전송을 시도하지 않는다. 그러나, 드문 경우로, 이중 전달이 발생할 수 있다. 예를 들어, 훅을 전송하는 도중에 kubelet이 재시작된다면, Kubelet이 구동된 후에 해당 훅은 재전송될 것이다.
훅 핸들러 디버깅
훅 핸들러의 로그는 파드 이벤트로 노출되지 않는다. 만약 핸들러가 어떠한 이유로 실패하면, 핸들러는 이벤트를 방송한다. PostStart의 경우 FailedPostStartHook 이벤트이며, PreStop의 경우 FailedPreStopHook 이벤트이다. 실패한 FailedPostStartHook 이벤트를 직접 생성하려면, lifecycle-events.yaml 파일을 수정하여 postStart 명령을 "badcommand"로 변경하고 이를 적용한다.
쿠버네티스에서 컨트롤러는 클러스터 의 상태를 관찰 한 다음, 필요한 경우에 생성 또는 변경을 요청하는 컨트롤 루프이다.
컨트롤러는 적어도 하나 이상의 쿠버네티스 리소스 유형을 추적한다. 이 오브젝트 는 의도한 상태를 표현하는 사양 필드를 가지고 있다. 해당 리소스의 컨트롤러(들)은 현재 상태를 의도한 상태에 가깝게 만드는 역할을 한다.
API 서버를 통한 제어
직접 제어
작업이 발생함에 따라 어떤 시점에서든 클러스터가 변경 될 수 있으며 컨트롤 루프가 자동으로 실패를 바로잡는다.
특정 컨트롤 루프 (컨트롤러)는 의도한 상태로서 한 종류의 리소스를 사용
잡 컨트롤러는 잡 오브젝트(새 작업을 발견하기 위해)와 파드 오브젝트(잡을 실행하고, 완료된 시기를 확인하기 위해)를 추적
디플로이먼트 컨트롤러와 잡 컨트롤러는 쿠버네티스의 자체("내장" 컨트롤러)로 제공되는 컨트롤러
레이블은 오브젝트의 특성을 식별하는 데 사용되어 사용자에게 중요하지만, 코어 시스템에 직접적인 의미는 없다
오브젝트에 붙여진 레이블 키는 고유해야 한다는 것을 기억해야 한다.
유효한 레이블 값은 다음과 같다.
63 자 이하여야 하고 (공백일 수도 있음),
(공백이 아니라면) 시작과 끝은 알파벳과 숫자([a-z0-9A-Z])이며,
알파벳과 숫자, 대시(``), 밑줄(_), 점(.)을 중간에 포함할 수 있다.
일치성 기준
일치하는 오브젝트는 추가 레이블을 가질 수 있지만, 레이블의 명시된 제약 조건을 모두 만족해야 한다. =,==,!= 이 세 가지 연산자만 허용
집합성 기준 요건
집합성 기준 레이블 요건에 따라 값 집합을 키로 필터링할 수 있다. in,notin과 exists(키 식별자만 해당)의 3개의 연산자를 지원
쿠버네티스 네트워킹은 다음의 네 가지 문제를 해결한다.
파드 내의 컨테이너는 루프백(loopback)을 통한 네트워킹을 사용하여 통신한다.
클러스터 네트워킹은 서로 다른 파드 간의 통신을 제공한다.
서비스 리소스를 사용하면 파드에서 실행 중인 애플리케이션을 클러스터 외부에서 접근할 수 있다.
NodePort, LoadBalancer ?
또한 서비스를 사용하여 서비스를 클러스터 내부에서만 사용할 수 있도록 게시할 수 있다.
ClusterIP ?
서비스 리소스
쿠버네티스에서 서비스는 파드의 논리적 집합과 그것들에 접근할 수 있는 정책을 정의하는 추상적 개념이다.
(때로는 이 패턴을 마이크로-서비스라고 한다.) 서비스가 대상으로 하는 파드 집합은 일반적으로 셀렉터 가 결정한다.
셀렉터가 있는(?) 서비스
셀렉터가 없는 서비스
서비스는 일반적으로 셀렉터를 이용하여 쿠버네티스 파드에 대한 접근을 추상화하지만,
셀렉터 대신 매칭되는(corresponding) 엔드포인트와 함께 사용되면 다른 종류의 백엔드도 추상화할 수 있으며, 여기에는 클러스터 외부에서 실행되는 것도 포함된다.
프로덕션 환경에서는 외부 데이터베이스 클러스터를 사용하려고 하지만, 테스트 환경에서는 자체 데이터베이스를 사용한다.
한 서비스에서 다른 네임스페이스 또는 다른 클러스터의 서비스를 지정하려고 한다.
워크로드를 쿠버네티스로 마이그레이션하고 있다. 해당 방식을 평가하는 동안, 쿠버네티스에서는 백엔드의 일부만 실행한다.
초과 용량 엔드포인트
엔드포인트 리소스에 1,000개가 넘는 엔드포인트가 있는 경우 쿠버네티스 v1.22(또는 그 이상)
클러스터는 해당 엔드포인트에 endpoints.kubernetes.io/over-capacity: truncated 어노테이션을 추가한다.
이 어노테이션은 영향을 받는 엔드포인트 오브젝트가 용량을 초과했으며 엔드포인트 컨트롤러가 엔드포인트의 수를 1000으로 줄였음을 나타낸다.
엔드포인트슬라이스
엔드포인트슬라이스는 엔드포인트에 보다 확장 가능한 대안을 제공할 수 있는 API 리소스이다.
개념적으로 엔드포인트와 매우 유사하지만, 엔드포인트슬라이스를 사용하면 여러 리소스에 네트워크 엔드포인트를 분산시킬 수 있다.
기본적으로, 엔드포인트슬라이스는 100개의 엔드포인트에 도달하면 "가득찬 것"로 간주되며, 추가 엔드포인트를 저장하기 위해서는 추가 엔드포인트슬라이스가 생성된다.
가상 IP와 서비스 프록시
쿠버네티스 클러스터의 모든 노드는 kube-proxy를 실행한다.
kube-proxy는 [ExternalName](<https://kubernetes.io/ko/docs/concepts/services-networking/service/#externalname>) 이외의 유형의 서비스에 대한 가상 IP 형식을 구현한다.
라운드-로빈 DNS를 사용하지 않는 이유
서비스에 프록시를 사용하는 데는 몇 가지 이유가 있다.
레코드 TTL을 고려하지 않고, 만료된 이름 검색 결과를 캐싱하는 DNS 구현에 대한 오래된 역사가 있다.
일부 앱은 DNS 검색을 한 번만 수행하고 결과를 무기한으로 캐시한다.
앱과 라이브러리가 적절히 재-확인을 했다고 하더라도, DNS 레코드의 TTL이 낮거나 0이면 DNS에 부하가 높아 관리하기가 어려워 질 수 있다.
구성
kube-proxy는 구성에 따라 결정되는 여러 모드에서 기동될 수 있다.
kube-proxy의 구성은 컨피그맵(ConfigMap)을 통해 이루어진다. 그리고 해당 kube-proxy를 위한 컨피그맵은 실효성있게 거의 대부분의 kube-proxy의 플래그의 행위를 더 이상 사용하지 않도록 한다.
kube-proxy를 위한 해당 컨피그맵은 기동 중 구성의 재적용(live reloading)은 지원하지 않는다.
kube-proxy를 위한 컨피그맵 파라미터는 기동 시에 검증이나 확인을 하지 않는다.
예를 들어, 운영 체계가 iptables 명령을 허용하지 않을 경우, 표준 커널 kube-proxy 구현체는 작동하지 않을 것이다.
마찬가지로, netsh을 지원하지 않는 운영 체계에서는, 윈도우 유저스페이스 모드로는 기동하지 않을 것이다.
유저 스페이스(User space) 프록시 모드
이 모드에서는, kube-proxy는 쿠버네티스 컨트롤 플레인의 서비스 및 엔드포인트 오브젝트의 추가와 제거를 감시한다.
kube-proxy는 사용할 백엔드 파드를 결정할 때 서비스의 SessionAffinity 설정을 고려한다.
마지막으로, 유저-스페이스 프록시는 서비스의 clusterIP (가상)와 port 에 대한 트래픽을 캡처하는 iptables 규칙을 설치한다.
iptables 프록시 모드
이 모드에서는, kube-proxy는 쿠버네티스 컨트롤 플레인의 서비스, 엔드포인트 오브젝트의 추가와 제거를 감시한다.
IPVS 프록시 모드
기능 상태: Kubernetes v1.11 [stable]
ipvs 모드에서는, kube-proxy는 쿠버네티스 서비스와 엔드포인트를 감시하고, netlink 인터페이스를 호출하여 그에 따라 IPVS 규칙을 생성하고 IPVS 규칙을 쿠버네티스 서비스와 엔드포인트와 주기적으로 동기화한다.
자신의 IP 주소 선택
https://kubernetes.io/ko/docs/concepts/services-networking/service/#자신의-ip-주소-선택
트래픽 정책
https://kubernetes.io/ko/docs/concepts/services-networking/service/#트래픽-정책
서비스 디스커버리하기
https://kubernetes.io/ko/docs/concepts/services-networking/service/#서비스-디스커버리하기
헤드리스(Headless) 서비스
https://kubernetes.io/ko/docs/concepts/services-networking/service/#헤드리스-headless-서비스
때때로 로드-밸런싱과 단일 서비스 IP는 필요치 않다. 이 경우, "헤드리스" 서비스라는 것을 만들 수 있는데, 명시적으로 클러스터 IP (.spec.clusterIP)에 "None"을 지정한다.
쿠버네티스의 구현에 묶이지 않고, 헤드리스 서비스를 사용하여 다른 서비스 디스커버리 메커니즘과 인터페이스할 수 있다.
서비스 퍼블리싱 (ServiceTypes)
애플리케이션 중 일부(예: 프론트엔드)는 서비스를 클러스터 밖에 위치한 외부 IP 주소에 노출하고 싶은 경우가 있을 것이다.
쿠버네티스 ServiceTypes는 원하는 서비스 종류를 지정할 수 있도록 해준다. 기본 값은 ClusterIP이다.
Type 값과 그 동작은 다음과 같다.
ClusterIP: 서비스를 클러스터-내부 IP에 노출시킨다. 이 값을 선택하면 클러스터 내에서만 서비스에 도달할 수 있다. 이것은 ServiceTypes의 기본 값이다.
[NodePort](<https://kubernetes.io/ko/docs/concepts/services-networking/service/#type-nodeport>):
고정 포트 (NodePort)로 각 노드의 IP에 서비스를 노출시킨다. NodePort 서비스가 라우팅되는 ClusterIP 서비스가 자동으로 생성된다.
<NodeIP>:<NodePort>를 요청하여, 클러스터 외부에서 NodePort 서비스에 접속할 수 있다.
[LoadBalancer](<https://kubernetes.io/ko/docs/concepts/services-networking/service/#loadbalancer>):
클라우드 공급자의 로드 밸런서를 사용하여 서비스를 외부에 노출시킨다. 외부 로드 밸런서가 라우팅되는 NodePort와 ClusterIP 서비스가 자동으로 생성된다.
[ExternalName](<https://kubernetes.io/ko/docs/concepts/services-networking/service/#externalname>):
값과 함께 CNAME 레코드를 리턴하여, 서비스를 externalName 필드의 콘텐츠 (예:foo.bar.example.com)에 매핑한다. 어떤 종류의 프록시도 설정되어 있지 않다.
참고: ExternalName 유형을 사용하려면 kube-dns 버전 1.7 또는 CoreDNS 버전 1.7 이상이 필요하다.
인그레스를 사용하여 서비스를 노출시킬 수도 있다. 인그레스는 서비스 유형이 아니지만, 클러스터의 진입점 역할을 한다.
동일한 IP 주소로 여러 서비스를 노출시킬 수 있기 때문에 라우팅 규칙을 단일 리소스로 통합할 수 있다.
NodePort 유형
https://kubernetes.io/ko/docs/concepts/services-networking/service/#type-nodeport
로드밸런서 유형
https://kubernetes.io/ko/docs/concepts/services-networking/service/#loadbalancer
AWS에서 TLS 지원
https://kubernetes.io/ko/docs/concepts/services-networking/service/#ssl-support-on-aws
AWS의 ELB 접근 로그
https://kubernetes.io/ko/docs/concepts/services-networking/service/#aws의-elb-접근-로그
AWS의 연결 드레이닝(Draining)
https://kubernetes.io/ko/docs/concepts/services-networking/service/#aws의-연결-드레이닝-draining
AWS의 네트워크 로드 밸런서 지원
https://kubernetes.io/ko/docs/concepts/services-networking/service/#aws-nlb-support
ExternalName 유형
https://kubernetes.io/ko/docs/concepts/services-networking/service/#externalname
외부 IP
https://kubernetes.io/ko/docs/concepts/services-networking/service/#외부-ip
https://kubernetes.io/ko/docs/concepts/services-networking/service/#the-gory-details-of-virtual-ips
충돌 방지
**type: ClusterIP 서비스의 IP 주소 범위
서비스 IP 주소
유저스페이스 (Userspace)
https://kubernetes.io/ko/docs/concepts/services-networking/service-topology/
쿠버네티스는 파드와 서비스를 위한 DNS 레코드를 생성한다. 사용자는 IP 주소 대신에 일관된 DNS 네임을 통해서 서비스에 접속할 수 있다.
A/AAAA 레코드
"노멀"(헤드리스가 아닌) 서비스는 서비스 IP 계열에 따라 my-svc.my-namespace.svc.cluster-domain.example
형식의 이름을 가진 DNS A 또는 AAAA 레코드가 할당된다. 이는 서비스의 클러스터 IP로 해석된다.
"헤드리스"(클러스터 IP가 없는) 서비스 또한 서비스 IP 계열에 따라 my-svc.my-namespace.svc.cluster-domain.example
형식의 이름을 가진 DNS A 또는 AAAA 레코드가 할당된다. 노멀 서비스와는 다르게 이는 서비스에 의해 선택된 파드들의 IP 집합으로 해석된다.
클라이언트는 해석된 IP 집합에서 IP를 직접 선택하거나 표준 라운드로빈을 통해 선택할 수 있다.
SRV 레코드
SRV 레코드는 노멀 서비스 또는 헤드리스 서비스에 속하는 네임드 포트를 위해 만들어졌다.
각각의 네임드 포트에 대해서 SRV 레코드는 다음과 같은 형식을 가질 수 있다.
my-port-name._my-port-protocol.my-svc.my-namespace.svc.cluster-domain.example.
정규 서비스의 경우, 이는 포트 번호와 도메인 네임으로 해석된다. my-svc.my-namespace.svc.cluster-domain.example.
헤드리스 서비스의 경우, 서비스를 지원하는 각 파드에 대해 하나씩 복수 응답으로 해석되며 이 응답은 파드의 포트 번호와 도메인 이름을 포함한다.
auto-generated-name.my-svc.my-namespace.svc.cluster-domain.example.
A/AAAA 레코드
일반적으로 파드에는 다음과 같은 DNS 주소를 갖는다.
pod-ip-address.my-namespace.pod.cluster-domain.example.
예를 들어, default 네임스페이스의 파드에 IP 주소 172.17.0.3이 있고, 클러스터의 도메인 이름이 cluster.local 이면, 파드는 다음과 같은 DNS 주소를 갖는다.
172-17-0-3.default.pod.cluster.local.
서비스에 의해 노출된 모든 파드는 다음과 같은 DNS 주소를 갖는다.
pod-ip-address.service-name.my-namespace.svc.cluster-domain.example.
파드의 hostname 및 subdomain 필드
파드가 생성되면 hostname은 해당 파드의 metadata.name 값이 된다.
파드 스펙(Pod spec)에는 선택적 필드인 hostname이 있다. 이 필드는 파드의 호스트네임을 지정할 수 있다.
hostname 필드가 지정되면, 파드의 이름보다 파드의 호스트네임이 우선 시 된다. 예를 들어 hostname 필드가 "my-host"로 설정된 파드는 호스트네임이 "my-host"로 설정된다.
또한, 파드 스펙에는 선택적 필드인 subdomain이 있다. 이 필드는 서브도메인을 지정할 수 있다.
예를 들어 "my-namespace" 네임스페이스에서, hostname 필드가 "foo"로 설정되고, subdomain 필드가 "bar"로 설정된 파드는 전체 주소 도메인 네임(FQDN)을 가지게 된다.
"foo.bar.my-namespace.svc.cluster-domain.example".
https://kubernetes.io/ko/docs/concepts/services-networking/connect-applications-service/
서비스 생성하기
평평하고 넓은 클러스터 전체의 주소 공간에서 nginx를 실행하는 파드가 있다고 가정하자.
이론적으로는 이러한 파드와 직접 대화할 수 있지만, 노드가 죽으면 어떻게 되는가? 파드가 함께 죽으면 디플로이먼트에서 다른 IP를 가진 새로운 파드를 생성한다. 이 문제를 서비스가 해결한다.
쿠버네티스 서비스는 클러스터 어딘가에서 실행되는 논리적인 파드 집합을 정의하고 추상화함으로써 모두 동일한 기능을 제공한다.
생성시 각 서비스에는 고유한 IP 주소(clusterIP라고도 한다)가 할당된다. 이 주소는 서비스의 수명과 연관되어 있으며, 서비스가 활성화 되어 있는 동안에는 변경되지 않는다.
파드는 서비스와 통신하도록 구성할 수 있으며, 서비스와의 통신은 서비스의 맴버 중 일부 파드에 자동적으로 로드-밸런싱 된다.
80포트로 서비스 생성하기
apiVersion: v1
kind: Service
metadata:
name: my-nginx
labels:
run: my-nginx
spec:
ports:
- port: 80
protocol: TCP
selector:
run: my-nginx프로젝트로서 쿠버네티스는 AWS, GCE와 nginx 인그레스 컨트롤러를 지원하고 유지한다.
인그레스는 클러스터 외부에서 클러스터 내부 서비스로 HTTP와 HTTPS 경로를 노출한다. 트래픽 라우팅은 인그레스 리소스에 정의된 규칙에 의해 컨트롤된다.
인그레스 컨트롤러가 있어야 인그레스를 충족할 수 있다. 인그레스 리소스만 생성한다면 효과가 없다.
서비스 내부 트래픽 정책 을 사용하면 내부 트래픽 제한이 트래픽이 시작된 노드 내의 엔드포인트로만 내부 트래픽을 라우팅하도록 한다.
여기서 "내부" 트래픽은 현재 클러스터의 파드로부터 시작된 트래픽을 지칭한다. 이를 통해 비용을 절감하고 성능을 개선할 수 있다.
https://kubernetes.io/docs/tutorials/kubernetes-basics/explore/
쿠버네티스 파드에 대해 배운다.
쿠버네티스 노드에 대해 배운다.
배포된 애플리케이션의 문제를 해결한다.
kubectl get - 자원을 나열한다
kubectl describe - 자원에 대해 상세한 정보를 보여준다.
kubectl logs - 파드 내 컨테이너의 로그들을 출력한다
kubectl exec - 파드 내 컨테이너에 대한 명령을 실행한다.
https://kubernetes.io/docs/tutorials/kubernetes-basics/expose/
쿠버네티스의 서비스에 대해 배운다.
레이블과 레이블셀랙터 오브젝트가 어떻게 서비스와 연관되는지 이해한다.
서비스를 이용하여 쿠버네티스 클러스터 외부로 애플리케이션을 노출한다.
비록 각 파드들이 고유의 IP를 갖고 있기는 하지만, 그 IP들은 서비스의 도움없이 클러스터 외부로 노출되어질 수 없다.
서비스들은 여러분의 애플리케이션들에게 트래픽이 실릴 수 있도록 허용해준다. 서비스들은 ServiceSpec에서 type을 지정함으로써 다양한 방식들로 노출시킬 수 있다:
ClusterIP (기본값) - 클러스터 내에서 내부 IP 에 대해 서비스를 노출해준다. 이 방식은 오직 클러스터 내에서만 서비스가 접근될 수 있도록 해준다.
NodePort - NAT가 이용되는 클러스터 내에서 각각 선택된 노드들의 동일한 포트에 서비스를 노출시켜준다. <NodeIP>:<NodePort>를 이용하여 클러스터 외부로부터 서비스가 접근할 수 있도록 해준다. ClusterIP의 상위 집합이다.
LoadBalancer - (지원 가능한 경우) 기존 클라우드에서 외부용 로드밸런서를 생성하고 서비스에 고정된 공인 IP를 할당해준다. NodePort의 상위 집합이다.
ExternalName - CNAME 레코드 및 값을 반환함으로써 서비스를 externalName 필드의 내용(예를 들면, foo.bar.example.com)에 매핑한다. 어떠한 종류의 프록시도 설정되지 않는다. 이 방식은 kube-dns v1.7 이상 또는 CoreDNS 버전 0.0.8 이상을 필요로 한다.
다른 서비스 타입들에 대한 추가 정보는 소스 IP 이용하기 튜토리얼에서 확인 가능하다. 또한 서비스들로 애플리케이션에 접속하기도 참고해 보자.
서비스는 파드 셋에 걸쳐서 트래픽을 라우트한다. 여러분의 애플리케이션에 영향을 주지 않으면서 쿠버네티스에서 파드들이 죽게도 하고, 복제가 되게도 해주는 추상적 개념이다.
종속적인 파드들 사이에서의 디스커버리와 라우팅은 (하나의 애플리케이션에서 프로트엔드와 백엔드 컴포넌트와 같은) 쿠버네티스 서비스들에 의해 처리된다.
$ kubectl get pods
No resources found in default namespace.
$ kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 19s
$ kubectl expose deployment/kubernetes-bootcamp --type="NodePort" --port 8080
service/kubernetes-bootcamp exposed
$ kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 4m1s
kubernetes-bootcamp NodePort 10.105.92.96 <none> 8080:32377/TCP 15s
$ kubectl describe services/kubernetes-bootcamp
Name: kubernetes-bootcamp
Namespace: default
Labels: app=kubernetes-bootcamp
Annotations: <none>
Selector: app=kubernetes-bootcamp
Type: NodePort
IP Families: <none>
IP: 10.105.92.96
IPs: 10.105.92.96
Port: <unset> 8080/TCP
TargetPort: 8080/TCP
NodePort: <unset> 32377/TCP
Endpoints: 172.18.0.2:8080
Session Affinity: None
External Traffic Policy: Cluster
Events: <none>
$ export NODE_PORT=$(kubectl get services/kubernetes-bootcamp -o go-template='{{(index .spec.ports 0).nodePort}}')
$ echo NODE_PORT=$NODE_PORT
NODE_PORT=32377
$ curl $(minikube ip):$NODE_PORT
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-fb5c67579-c852d | v=1https://kubernetes.io/docs/tutorials/kubernetes-basics/scale/
kubectl을 사용해서 애플리케이션을 스케일한다.
지난 모듈에서 디플로이먼트를 만들고, 서비스를 통해서 디플로이먼트를 외부에 노출시켜 봤다.
해당 디플로이먼트는 애플리케이션을 구동하기 위해 단 하나의 파드만을 생성했었다. 트래픽이 증가하면, 사용자 요청에 맞추어 애플리케이션의 규모를 조정할 필요가 있다.
디플로이먼트의 복제 수를 변경하면 스케일링이 수행된다.
$ kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
kubernetes-bootcamp 1/1 1 1 22s
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
kubernetes-bootcamp-fb5c67579 1 1 1 17s
$ kubectl scale deployments/kubernetes-bootcamp --replicas=4
deployment.apps/kubernetes-bootcamp scaled
$ kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
kubernetes-bootcamp 4/4 4 4 53s
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kubernetes-bootcamp-fb5c67579-fkdr7 1/1 Running 0 24s 172.18.0.7 minikube <none> <none>
kubernetes-bootcamp-fb5c67579-fpfp9 1/1 Running 0 24s 172.18.0.9 minikube <none> <none>
kubernetes-bootcamp-fb5c67579-ms8h7 1/1 Running 0 24s 172.18.0.8 minikube <none> <none>
kubernetes-bootcamp-fb5c67579-wrfm4 1/1 Running 0 52s 172.18.0.3 minikube <none> <none>
$ kubectl describe deployments/kubernetes-bootcamp
Name: kubernetes-bootcamp
Namespace: default
CreationTimestamp: Mon, 10 Apr 2023 04:04:18 +0000
Labels: app=kubernetes-bootcamp
Annotations: deployment.kubernetes.io/revision: 1
Selector: app=kubernetes-bootcamp
Replicas: 4 desired | 4 updated | 4 total | 4 available | 0 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 25% max unavailable, 25% max surge
Pod Template:
Labels: app=kubernetes-bootcamp
Containers:
kubernetes-bootcamp:
Image: gcr.io/google-samples/kubernetes-bootcamp:v1
Port: 8080/TCP
Host Port: 0/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
Conditions:
Type Status Reason
---- ------ ------
Progressing True NewReplicaSetAvailable
Available True MinimumReplicasAvailable
OldReplicaSets: <none>
NewReplicaSet: kubernetes-bootcamp-fb5c67579 (4/4 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 66s deployment-controller Scaled up replica set kubernetes-bootcamp-fb5c67579 to 1
Normal ScalingReplicaSet 37s deployment-controller Scaled up replica set kubernetes-bootcamp-fb5c67579 to 4https://kubernetes.io/docs/tutorials/kubernetes-basics/update/
kubectl을 이용하여 롤링 업데이트 수행하기
사용자들은 애플리케이션이 항상 가용한 상태일 것이라 여기고 개발자들은 하루에 여러번씩 새로운 버전을 배포하도록 요구 받고있다.
쿠버네티스에서는 이것을 롤링 업데이트를 통해 이루고 있다.
롤링 업데이트는 파드 인스턴스를 점진적으로 새로운 것으로 업데이트하여 디플로이먼트 업데이트가 서비스 중단 없이 이루어질 수 있도록 해준다.
새로운 파드는 가용한 자원을 보유한 노드로 스케줄될 것이다.
이전 모듈에서 여러 개의 인스턴스를 동작시키도록 애플리케이션을 스케일했다.
이것은 애플리케이션의 가용성에 영향을 미치지 않으면서 업데이트를 수행하는 것에 대한 요구이다.
기본적으로, 업데이트가 이루어지는 동안 이용 불가한 파드의 최대 개수와 생성 가능한 새로운 파드의 최대 개수는 하나다.
두 옵션은 (파드에 대한) 개수 또는 백분율로 구성될 수 있다.
쿠버네티스에서, 업데이트는 버전으로 관리되고 어떠한 디플로이먼트 업데이트라도 이전의 (안정적인) 버전으로 원복이 가능하다.
롤링 업데이트는 다음 동작들을 허용해준다:
하나의 환경에서 또 다른 환경으로의 애플리케이션 프로모션 (컨테이너 이미지 업데이트를 통해)
이전 버전으로의 롤백
서비스 중단 없는 애플리케이션의 지속적인 통합과 지속적인 전달
DEVOTEE를 활성화 시키면
지금 작성한 댓글에 AI가 댓글을 달아줍니다.