-
쿠버네티스 ① 메인 K8s component (1)네트워크 & 인프라 2022. 10. 8. 13:15
인프라 내용을 학습할 때 항상 나오는 쿠버네티스...!
간단하게나마 알면 도움이 될 것같아 영상을 보고 학습하였다. 💪
학습 내용의 출처는 모두 아래 두영상이다! 🙌
참고한 영상 👇🏼
- 모든 내용은 윗 영상을 캡쳐 및 정리한 내용입니다! 🙌
쿠버네티스란?
- 오픈소스 컨테이너 orchestration tool
- monolith → msa
- 구글에 의해 개발됨 (도커 등등)
- 다른 개발 환경에서의 컨테이너 어플리케이션을 다루는데 도움을 줌
왜 사용하는가?
- monolith → msa
- 컨테이너의 사용이 증가
- 많은 컨테이너를 다루는데 어려움이 증가
orchestration tool 장점
- 컨테이너 → 용량이 작아 빠른 배포를 위해 사용됨
- orchestration tool이 컨테이너를 알아서 배치 및 관리
- 가용성이 높고 중단 시간이 없음
- no dump time
- 유저가 빠른 반응을 받을 수 있어 확장성이 높고 성능이 높음
- 서버가 다운되는 경우 회복이 가능 ( backup and restore )
- backup data, lateness
- 루즈 데이터 가능성 작음
메인 k8s 컴포넌트
1) Node & Pod
- Node
- Pod
- 컨테이너 → 1개의 어플리케이션을 담당
- 쿠버네티스에서는 pod이 컨테이너를 표현하는 K8s API의 최소단위 ⇒ k8s의 가장 작은 단위
- 보통 pod마다 1개의 어플리케이션을 가지지만 pod에서 하나 또는 여러개의 컨테이너를 포함 가능
- 오직 쿠버네티스 계층과 소통함
- 컨테이너를 대상으로 추상화
- 컨테이너가 교체 가능
- 각각의 pod은 각각의 ip 주소를 가짐
- 자신만의 ip 주소를 가지고 서로 상호작용 할 수 있음
- ex ) internal ip, public ip 등
- 자신만의 ip 주소를 가지고 서로 상호작용 할 수 있음
- 재생산시 새로운 ip 주소를 가짐
- ip 주소는 데이터베이서 컨테이너를 잃거나 중단되었을 때 새로운 pod으로 쉽게 교체가능
- 재할당이 가능
- 1) single container pod 생성하기
- run CLI 사용
- $ kubectl run webserver —image=nginx:1.14
- pod YAML을 사용
- $kubectl create -f pod-nginx.yaml
- run CLI 사용
- 2) multi container pod 생성하기
- pod 안의 여러개의 컨테이너는 같은 Ip 주소를 사용
- 실행중인 컨테이너로 들어가기
- $ kubectl exec [multipod / pod 이름] -it(interactive 하게 sudo 터미널 사용) -c [centos-container / 컨테이너 이름] — / bin / bash(bash shell 실행)
- $ kubectl logs multipod -c nginx-container
- 3) self-healing pod
- 지속적으로 pod이 살아있음을 체크하고(kubelet으로 컨테이너 진단) 건강한 컨테이너만을 이용해서 애플리케이션 서비스를 제공함
- livenessProbe
- pod이 계속 실행할 수 있음 보장
- pod의 sepc에 정의
- 메커니즘
- 컨테이너를 재시작해도 pod은 그대로 이기 때문에 Ip 주소는 바뀌지 않고 유지 가능
- httpGet probe
- 지정한 IP주소, port, path에 HTTP GET요청을 보내 해당 컨테이너가 응답하는지 확인
- 반환코드가 200이 아닌 값일 경우 오류 발생 → 컨테이너 재시작
- tcpSocket probe
- 지정된 포트에 TCP 연결을 시도
- 연결되지 않으면 컨테이너를 재시작
- exec probe
- exec 명령을 전달
- 명령 종료 코드가 0이 아닌 경우 컨테이너를 재시작
- 매개 변수
- periodSeconds
- health check 반복 실행 시간 (초)
- initialDelaySeconds
- pod 실행 후 delay할 시간 (초)
- timeoutSeconds
- health check 후 응답을 기다리는 시간 (초)
- periodSeconds
- 4) init container를 적용한 pod
- 환경구성, 초기화 세팅을 지원해주는 컨테이너
- 앱 컨테이너가 실행 전에 미리 동작시킬 컨테이너
- 초기화 컨테이너가 모두 실행에 성공된 후 앱 컨테이너가 실행됨
- ex) 로그인을 할 때
- init 컨테이너에서 로그인할 때 필요한 정보들을 가지고 옴
- 성공적으로 가지고 왔을 경우에만 메인 컨테이너가 실행이 됨
- 5) infra container(pause)
- pod이 생성될때 하나씩 생성되고 pod이 제거될때 같이 사라짐
- pod의 환경을 만들어주는 컨테이너
- 6) static pod
- API의 도움없이 kubelet이라는 데몬에 의해서 static pod 디렉토리 안에있는 YAML파일을 저장해두면 알아서 실행
- ex) 마스터 노드의 4가지 프로세스도 모두 static pod 형식으로 실행된 것
- 경로는 이미 static Pod path로 정의되어 있음
- 새로운 static pod 내용을 추가하게 되면 master가 아닌 node 들 중 하나에 배치됨
- pod에 리소스(cpu, memory) 할당하기
- pod하나를 사용하더라도 리소스를 어느정도 사용할지 limit해주어야 함 (과사용 방지)
- 컨테이너 별로 요구조건(request)을 이용하여 최소한의 cpu, 메모리가 남아있는 곳(pod)에 컨테이너를 배치할 수 있도록 설정
- Pod Resource 요청 및 제한
- Resource Requests
- pod를 실행하기 위한 최소 리소스 양을 요청
- ex) cpu: 200m (1000밀리코어 = 1코어) = 1/5 코어
- Resource Limits
- pod가 사용할 수 있는 최대 리소스 양을 제한
- Memory limit을 초과해서 사용되는 pod는 종료(OOM Kill)되며 재스케줄링됨
- pod의 환경변수 설정하기
- pod내의 컨테이너가 실행될 때 필요로 하는 변수
- 컨테이너 제작 시 미리 정의
- specification의 env를 이용하여 pod 실행 시 미리 정의된 컨테이너의 환경변수를 변경 가능
- pod 구성 패턴의 종류
- pod을 구성하고 실행하는 패턴
- multi-container pod
- sidecar
- pod안에 컨테이너가 2개 ⇒ 함께 동작하여 두개가 모두 있어야 동작
- 하나는 web 서버(로그 생성)
- 하나는 sidecar 서버(생성된 로그파일을 버킷으로 보냄)
- adapter
- 외부의 서비스 정보를 Adapter가 받아서 web 서버(UI정보) 컨테이너에게 전달
- Adapter는 외부 서비스의 정보를 전달
- ambassador
- web 서버가 고객들과 통신하여 생성된 데이터를 Ambassador가 캐시로 저장하여 이용 (로드밸런서 역할, 분배 저장)
- Ambassador는 웹서버가 받은 정보를 저장
- sidecar
2) service 와 Ingress
- Service
- 각자의 서비스를 가져 각각의 pod에 영구적인 ip 주소를 지님
- pod의 라이프사이클과 서비스는 개별
- 두가지 기능
- 영구 ip : DNS 안의 이름 (persistent static ip)
- 로드밸런서 : 요청을 포워딩 (전달)
- 쿠버네티스 네트워크
- 동일한 서비스를 제공하는 pod 그룹의 단일 진입점(Virtual IP) 제공
- stable 한 Ip주소를 가짐
- 각각의 Pod은 개인의 Ip주소를 가지는데 매번 pod이 중단되거나 새로 교체될 때마다 새로운 Ip주소를 가지게 되면 불편
- 로드밸런싱 기능을 가짐
- 컴포넌트 끼리의 결합도 감소
- 클러스터 내 외부와 상호작용
- service endpoints
- k8s가 생성
- 서비스와 이름이 같으면서 어떤 pod이 서비스의 members / endpoints인지 트래킹
- service port VS targetPort
- service port
- 임의의 번호
- targetPort
- 반드시 컨테이너가 듣고 있는 포트와 동일해야함
- service port
1) ClusterIP services
- 디폴트 타입 (타입이 specification에 정의되지 않아도 됨)
- MSA 애플리케이션이 배포될 때
- browser → ingress → service(internalService)의 IP주소와 port로 접근 → pod 이용
- 디폴트(10.96.0.0/12범위에서 할당)로 타입 설정이 불필요
- selector의 label이 동일한 pod들의 그룹으로 묶어 pod 그룹의 내부 단일 진입점(Virtual IP) 생성
- internal Service
- 클러스터 외부에서는 접근이 어려움 (클러스터 내부에서만 사용가능)
- 어떤 pod으로 접근할지, 어떤 port로 접근할지 어떻게 아는가?
- “selector” : 어떤 pod으로 갈지 설정
- “targetPort” : 포트번호 설정
+) Multi-Port services
- 모니터링 측정을 위한 두번째 컨테이너
- 이름을 정의해주어야 함
+) Headless services
- 사용 시기
- 클라이언트가 1개의 특정 pod과 소통하려고 할 때
- ClusterIP가 없는 서비스로 단일 진입점이 필요 없을 때 사용
- 여러개의 pod이 하나의 특정 pod과 직접적으로 얘기하려고 할 때
- 사용 예시
- stateful 어플리케이션 (ex)databases)
- pod 복사본이 동일하지 않음 (not identical)
- 지속적인 데이터 동기화 필요
- Service와 연결괸 pod의 endpoint로 DNS 레코드가 생성됨
- pod에 대한 endpoint를 DNS resolving service로 요청이 가능
- 클라이언트는 개별 pod의 Ip 주소를 알아야 함
- 방법 1) K8s API서버에게 API 콜
- K8s API에 너무 의존적임
- 비효율적
- 방법 2) DNS Lookup
- 서비스의 DNS Lookup이 하나의 Ip 주소(ClusterIP)를 반환
- ClusterIP 를 ”None”으로 설정하면 Pod IP 주소를 대신 반환함
- 방법 1) K8s API서버에게 API 콜
2) NodePort services
- 외부 트래픽이 각각의 worker 노드의 고정 포트로의 접근 권한 보유
- (기본적으로 클러스터 IP 생성함)클러스터 IP 생성 후 모든 워커 노드에 외부에서 접속가능 한 포트가 예약
- nodePort 사용시 ClusterIP가 자동으로 생성됨
- 클러스터 IP 생성 후 NodePort를 예약
- 외부에서 직접적으로 접근 권한을 갖게 되어 안전하지 않음
- ClusterIP 서비스 타입의 확장 버전
- 디폴트 NodePort 범위 → 30000 - 32767
- 외부 연결을 위한 것은 아님 ⇒ 테스트용으로는 사용할 수 있으나 production 모드에서는 사용하지 않음 (보안)
3) LoadBalancer services
- 외부에서 public 클라우드 provider의 로드밸런서를 통해서 접근이 가능
- 로드밸런서를 자동으로 프로비전 하는 기능 지원
- public cloud(AWS, Azure, GCP등)에서 운영이 가능
- 로드밸런서를 이용하면 nodePort와 ClusterIP가 자동으로 생성됨
- NodePort 서비스 타입의 확장 버전
- NodePort 예약 후 해당 NodePort로 외부 접근을 허용
- 실제 production 모드에서는 Ingress나 Loadbalancer를 사용
4) External Name
- 클러스터 안에서 외부에 접속 시 사용할 도메인을 등록해서 사용
- 클러스터 내부에서 External(외부)의 도메인을 설정
- DNS를 지원
- 클러스터 도메인이 실제 외부 도메인으로 치환되어 동작
- Ingress
- 요청을 cluster로 라우팅
- 웹기반의 서비스를 외부에서 접속이 가능하도록 도와줌
- HTTP나 HTTPS를 통해 클러스터 내부의 서비스를 외부로 노출
- Service에 외부 URL을 제공
- 트래픽을 로드밸런싱
- SSL 인증서 처리
- Virtual Hosting을 지정
- ex) 어플은 브라우저를 통해서 접근이 가능해야 함
- http://my-app-service-ip:port → external service (o)
- ex) https://my-app.com → Ingress 가 service로 포워딩 해준다.
- http://db-service-ip:port → internal service (x)
- http://my-app-service-ip:port → external service (o)
- 예시 웹페이지 구현)
- external service VS Ingress
- external service
- ip address : port (마지막 배포 형태가 아님)
- ingress
- 도메인 이름 (https://) (ip address and port가 공개되지 않음)
- external service
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: dashboard-ingress namespace: kubernetes-dashboard annotations: kubernetes.io/ingress.class: "nginx" spec: // routing rules rules: - host: dashboard.com http: paths: - path: / pathType: Exact backend: // forward request to the internal service service: name: kubernetes-dashboard port: number: 80
- internal service
- node Port가 없음
- 로드밸런서 대신에 디폴트 타입 : Cluster IP
- internal service에서 kubernetes 클러스터에 접근할 때
- 도메인 주소를 확인 및 검사
- 도메인 이름을 entry point인 internal service 노드의 ip주소로 매핑
- ingress controller
- YAML을 통해서 클러스터 안에 Ingress component를 생성할 때 필요
- ingress rules 검사 수행
- redirection을 관리
- 클러스터에 대한 entry point
- 많은 third-party implementation
- ex) k8s nginx ingress controller
- 클러스터가 운영되는 환경
- cloud service provider
- ex) AWS, Google Cloud, Linode
- k8s의 솔루션 밖에 존재
- 원하는 구성을 다양하게 할 수 있음
- 가상화된 로드밸런서를 가짐 (별도이 로드밸런서 주입 필요 X)
- Bare Metal
- 몇개의 entry point를 구성해야함
- 클러스터 내부 혹은 바깥에 서버가 분리됨
- ex) proxy server
- 분리된 서버로 public Ip 주소와 열린 posrts를 가짐
- 클러스터로 가능 entry point
- 요청이 proxy server로 전달 → proxy server 가 Ingress Controller 로 전달 → Ingress Controller가 Ingress 규칙 체크 → service로 전달
- cloud service provider
- Minikube에서 Ingress Controller 동작 확인하기
-
- minikube에 Ingress Controller 설치하기
- $ minikube addons enable ingress
- 자동으로 Ingress Controller가 포함된 K8s Nginx를 시작
- $ kubectl get pod -n kube-system 명령어로 컨트롤러 실행 확인 가능
- Ingress rule를 생성 및 적용
- 호스팅을 이용해서 쿠버네티스 대시보드에 접근하는 것을 가능하게 함
- dashboard.com으로 요청 → internal 또는 public service인 kubernetes-dashboard로 80번 포트로 요청을 넘김
- Ingress rule 적용 → Address 할당됨
- $ kubectl apply -f [YAML 파일]
-
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: dashboard-ingress namespace: kubernetes-dashboard annotations: kubernetes.io/ingress.class: "nginx" spec: rules: - host: dashboard.com http: paths: - path: / pathType: Exact backend: service: name: kubernetes-dashboard port: number: 80
- Ingress Default Backend
- $ kubectl describe ingress [ingress] -n [dashboard]
- Default Backend 확인 가능
- 없는 페이지 검색시 Default Backend가 작용하여 의미있는 메세지를 보여주기도 함
- $ kubectl describe ingress [ingress] -n [dashboard]
- 하나의 호스트에 여러 path를 이용하는 방법
- ex) Google은 하나의 도메인에 여러 서비스를 가짐
- 여러 서브 도메인이나 도메인을 갖는 방법
- TLS certificate 구성하기
- key는 tls.crt 와 tls.key로 구성
- 값은 파일 경로나 위치가 아닌 file contents로 구성
- 시크릿 component는 Ingress와 같은 네임 스페이스에 위치 해야함
3) configMap 와 secret
- 환경변수로서 사용하거나 properties 파일 용도로 사용
- ex) 데이터 베이스 URL은 보통 생성된 어플리케이션 안에 위치하여 rebuild 시에 이를 repo에 푸시하고 다시 pod에 가져오는 방식
- configMap
- 어플리케이션의 external configuration
- pod에 연결되어 있으면서 데이터를 받기 위한 용도로 사용됨
- 따라서 매번 새로운 이미지를 생성하거나 할 필요가 없음
- ex) database, url 설정 등
- 컨테이너 구성 정보를 한곳에 모아서 관리
- 그러나 보안상 credential은 configMap에 넣어선 안된다
- configMap의 일부분을 적용하기도 가능
- configMap의 볼륨으로 적용하기도 가능
- secret
- configMap과 같지만 secret 데이터를 보관하는데 사용됨
- 컨테이너가 사용하는 password, auth token, ssh key와 같은 중요한 정보를 저장하고 민감한 구성정보를 base64로 인코딩해서 한 곳에 모아서 관리
- Available Commands 에 따라 들어가는 옵션이 달라짐
- credentials를 plain text 타입이 아닌 base 64 encoded 타입으로 저장
- credentials, password, certificate와 같은 비밀 정보를 담음
- 기본적으로 빌트인 보안 메카니즘은 실행되지 않으므로 배포 이전에 생성되어야 함
- 데이터 전달 방법
- ---- 1) Command-line Argument
- ---- 2) Environment Variable
- ---- 3) Volume Mount
- 데이터 용량 제한
- secret etcd에 암호화 하지 않은 텍스트로 저장되므로 secret value가 커지면 메모리 용량을 많이 사용하게 됨
- secret의 최대 크기는 1MB
4) volumes
- 데이터 저장소
- 데이터베이스 컨테이너나 pod이 재실행 되는 경우에도 데이터를 일관성이고 신뢰성있게 보관
- 저장소를 쿠버네티스 클러스터의 pod이 아닌 local machine 또는 remote(k8s 클러스터 바깥에)에 위치
- 데이터를 영구히 저장 가능
- local인지 remote 저장소인지에 관계없이 외부 하드 드라이브로서 k8s 클러스터에 연결되어 k8s는 데이터의 영속성을 관리하지 않아도 됨
- 단 적절한 하드웨어에 데이터가 보관되는지 확인해야 함
- 쿠버네티스의 pod이 죽거나 중단된다면 ?
- 미리 여러개의 노드를 통해 모든 것을 복사 해놓음
- 프로덕션 모드에서도 pod을 재실행하거나 새로운 컨테이너를 짓는 동안 시간이 걸려 서비스가 중단되는 것을 방지
- 복사본은 같은 서비스에 연결되어있음
- 미리 여러개의 노드를 통해 모든 것을 복사 해놓음
- pod 의 blueprint 를 정의하여 얼마나 많은 pod이 관리되고 운영될 지 결정
- 쿠버네티스에서 볼륨을 이용한 데이터 영속화
- 저장소 요구사항
-
- 저장소는 pod 라이프사이클에 의존적이면 안됨
- 저장소는 모든 노드에 대해 사용 가능해야함
- 어떤 pod이 중단될지 모르기 때문에 모든 pod이 회복 가능하도록
- 클러스터가 중단되어도 저장소는 영향받지 않아야 함
-
1) Persistent Volume(PV)
- 클러스터 리소스 (마치 CPU RAM처럼)
- YAML파일에 의해 생성
- kind : PersistentVolume
- spec: 얼마나 큰 저장소인가 (물리 저장소처럼), 어떤 저장소인가 정의
- 쿠버네티스는 실제 저장소에 대해서는 관여 X
- 어떤 타입의 저장소를 사용할 건지 생성하고 관리하는 것은 사용자의 몫
- 네임 스페이스화 되어있지 않음
- Local, Remote 볼륨 타입
- 단 Local 볼륨타입의 경우 저장소 요구사항 2, 3 번을 위반함
- 따라서 항상 Remote 볼륨 타입을 사용
- 누구에 의해 만들어지는가?
- k8s admin이 클러스터와 리소스를 관리
- k8s user가 클러스터에 앱을 배포
- admin에 의해 저장소가 공급되면 이 저장소 backend에 의해 PersistentVolume이 생성됨
2) Persistent Volume Claim(PVC)
- 애플리케이션이 PV를 요구해야 함
- claim은 다음과 같은 정보를 가짐
- Volume 추상화 과정 (생성과정)
- 1) pod이 PVC에게 볼륨을 요구
- 2) claim이 클러스터에서 볼륨을 찾음
- 단, 클레임은 반드시 같은 네임스페이스에 존재해야 함
- 3) 볼륨이 실제 저장소 backend를 가지고 있음
- 4) 볼륨이 컨테이너에 마운트 됨
- 5) 볼륨이 pod에 마운트 됨
- 6) 컨테이너는 이를 이용해 읽고 쓰기 작업 수행 가능
- 7) 만약 pod이 중단되어도 같은 저장소를 공유하게 되므로 유지가 가능해짐
- volume에 많은 추상화가 존재하는 이유?
- 관리자는 볼륨을 배정 → PV
- 사용자는 볼륨을 생성해달라고 claim → PVC
- 사용자는 실제 저장소가 어디에 위치하는지 알 필요가 없어짐
- 사용자는 실제 저장소의 셋업과정을 알 필요가 없음
- 즉, 사용자는 앱을 배포하는 것에만 집중할 수 있게 됨
- ConfigMap 과 Secret
- 둘다 local 저장소
- PV 나 PVC에의해 생성되지 않음
- 쿠버네티스에 의해 관리됨
- 사용
- ConfigMap 또는 Secret 컴포넌트를 생성
- pod이나 container에 마운트
3) Storage Class
- 과정
- 관리자가 PV 동적으로 배정
- pod이 PVC를 이용해 PV를 요구 → 자동 생성
- PVC가 Storage Class에게 저장소를 요구
- SC가 claim 요구에 만족하는 PV를 생성
'네트워크 & 인프라' 카테고리의 다른 글
쿠버네티스 ③ 기본 Architecture (0) 2022.10.12 쿠버네티스 ② 메인 K8s component (2) (0) 2022.10.12 gRPC ③ gRPC + 스프링부트 프로젝트 구성해보기 (0) 2022.10.05 gRPC ② gRPC + 자바 프로젝트 구성해보기 (1) 2022.10.05 gRPC ① gRPC란 ( + Kotlin 설정) (1) 2022.09.30