CloudNet 가시다님이 진행하는 스터디 6주차 정리입니다.
[ 실습 환경 구성 ]
▶ k3s : Lightweight Kubernetes. Easy to install, half the memory, all in a binary of less than 100 MB
- rancher 회사에서 IoT 및 edge computing 디바이스 위에서도 동작할 수 있도록 만들어진 경량 k8s 입니다
- 장점 : 설치가 쉽다, 가볍다(etcd, cloud manager 등 무거운 컴포넌트 제거), 학습용 및 테스트 시 필요한 기능들은 대부분 탑재
What is K3s : K3s is a fully compliant Kubernetes distribution with the following enhancements
- Distributed as a single binary or minimal container image.
- Lightweight datastore based on sqlite3 as the defualt storage backend. etcd3, MySQL, and Postgres are also available.
- Wrapped in simple launcher that handles a lot of the complexity of TLS and options.
- Secure by default with reasonable defaults for lightweight environments.
- Operation of all Kubernetes control plane components is encapsulated in a single binary and process, allowing K3s to automate and manage complex cluster operations like distributing certificates.
- External dependencies have been minimized; the only requirements are a modern kernel and cgroup mounts.
- Packages the required dependencies for easy "batteries-included" cluster creation :
- containerd / cri-dockerd container runtime (CRI)
- Flannel Container Network Interface (CNI)
- CoreDNS Cluster DNS
- Traefik Ingress controller
- ServiceLB Load-Balancer controller
- Kube-router Network Policy controller
- Local-path-provisioner Persistent Volume controller
- Spegel distributed container image registry mirror
- Host utilities (iptables, socat, etc)
Architecture
- Servers and Agents : 서버(Controlplane)와 에이전트 (Work nodes)
- A Server node is defined as a host running the k3s server command, with control-plane and datastore components managed by K3s.
- An agent node is defined as a host running the k3s agent command, without any datastore or control-plane components.
- Both servers and agents run the kubelet, container runtime, and CNI. See the Advanced Options documentation for more information on running agentless servers.
- Single-server Setup with an Embedded DB : 1대 K3s 서버(경량 DB = SQLite), 필요한 만큼의 k3s Agents(워커 노드들)
- High-Availability K3s : EmbeddedDB, External DB
▶ k3s 기본 정보 확인 : k8s v1.30.x -> 현재 ingress-nginx controller이 1.30.x 까지 버전 호환 테스트 완료
0. Ingress 요약
인그레스(Ingress)를 통한 통신 흐름
인그레스(Ingress)? : URI, 호스트네임, 경로 등과 같은 웹 개념을 이해하는 프로토콜-인지형(Protocol-aware configuration) 설정 메커니즘을 이용하여 HTTP(혹은 HTTPS) 네트워크 서비스를 사용 가능하게 한다. 인그레스 개념은 쿠버네티스 API를 통해 정의한 규칙에 기반하여 트래픽을 다른 백엔드에 매핑할 수 있게 해준다. 클러스터 내의 서비스에 대한 외부 접근을 관리하는 API 오브젝트이며, 일반적으로 HTTP를 관리한다. 인그레스는 부하 분산, SSL 종료, 명칭 기반의 가상 호스팅을 제공할 수 있다. 용어 - 노드(Node) : 클러스터의 일부이며, 쿠버네티스에 속한 워커 머신 - 클러스터(Cluster) : 쿠버네티스에서 관리되는 컨테이너화 된 애플리케이션을 실행하는 노드 집합. 이 예시와 대부분의 일반적인 쿠버네티스 배포에서 클러스터에 속한 노드는 퍼블릭 인터넷의 일부가 아니다. - 에지 라우터(Edge router) : 클러스터에 방화벽 정책을 적용하는 라우터. 이것은 클라우드 공급자 또는 물리적 하드웨어의 일부에서 관리하는 게이트웨이일 수 있다 - 클러스터 네트워크(Cluster Network) : 쿠버네티스 네트워킹 모델에 따라 클러스터 내부에서 통신을 용이하게 하는 논리적 또는 물리적 링크 집합 - 서비스 : 레이블 셀렉터를 사용해서 파드 집합을 식별하는 쿠버네티스 서비스. 달리 언급하지 않으면 서비스는 클러스터 네트워크 내에서만 라우팅 가능한 가상 IP를 가지고 있다고 가정한다 인그레스는 클러스터 외부에서 클러스터 내부 서비스로 HTTP와 HTTPS 경로를 노출한다. 트래픽 라우팅은 인그레스 리소스에 정의된 규칙에 의해 컨트롤 된다. 출처 : https://kubernetes.io/ko/docs/concepts/services-networking/ingress/ 인그레스는 외부에서 서비스로 접속이 가능한 URL, 로드 밸런스 트래픽, SSL/TLS 종료 그리고 이름-기반의 가상 호스팅을 제공하도록 구성할 수 있다. 인그레스 컨트롤러는 일반적으로 로드 밸런서를 사용해서 인그레스를 수행할 책임이 있으며, 트래픽을 처리하는데 도움이 되도록 에지 라우터 또는 추가 프런트 엔드를 구성할 수도 있다. 인그레스는 임의의 포트 또는 프로토콜을 노출시키지 않는다. HTTP와 HTTPS 이외의 서비스를 인터넷에 노출하려면 보통 Service.Type = NodePort 또는 Service.Type = LoadBalancer 유형의 서비스를 사용한다. |
Nginx 인그레스 컨트롤러 경우 : 외부에서 인그레스로 접속 시 Nginx 인그레스 컨트롤러 파드로 인입되고, 이후 애플리케이션 파드의 IP로 직접 통신
클러스터 내부를 외부에 노출
1. 파드 생성 : k8s 클러스터 내부에서만 접속
2. 서비스(Cluster Type) 연결 : k8s 클러스터 내부에서만 접속
- 동일한 애플리케이션의 다수의 파드의 접속을 용이하게 하기 위한 서비스에 접속
3. 서비스(NodePort Type) 연결 : 외부 클라이언트가 서비스를 통해서 클러스터 내부의 파드로 접속
- 서비스(NodePort Type)의 일부 단점을 보완한 서비스(LoadBalancer Type)도 있습니다.
4. 인그레스 컨트롤러 파드를 배치 : 서비스 앞단에 HTTP 고급 라우팅 등 기능 동작을 위한 배치
- 인그레스(정책)이 적용된 인그레스 컨트롤러 파드(예. nginx pod)를 앞단에 배치하여 고급 라우팅 등 기능을 제공
5. 인그레스 컨트롤러 파드 이중화 구성 : Active(Leader) - Standby(Follower)로 Active 파드 장애에 대비
6. 인그레스 컨트롤러 파드를 외부에 노출 : 인그레스 컨트롤러 파드를 외부에서 접속하기 위해서 노출(expose)
- 인그레스 컨트롤러 노출 시 서비스(NodePort Type) 보다는 좀 더 많은 기능을 제공하는 서비스(LoadBalancer Type)를 권장합니다(80/443 포트 오픈 시)
7. 인그레스와 파드간 내부 연결의 효율화 방안 : 인그레스 컨트롤러 파드(Layer 7 동작)에서 서비스 파드의 IP로 직접 연결
- 인그레스 컨트롤러 파드는 k8s API 서버로부터 서비스의 엔드포인트 정보(파드 IP)를 획득 후 바로 파드의 IP로 연결
- 지원되는 인그레스 컨트롤러 : Nginx, Traefix 등 현재 대부분의 인그레스 컨트롤러가 지원함
1. 인그레스(Ingress) 소개
인그레스 소개 : 클러스터 내부의 서비스(ClusterIP, NodePort, LoadBalancer)를 외부로 노출(HTTP/HTTPS) - Web Proxy 역할
- Make your HTTP (or HTTPS) network service available using a protocol-aware configuration mechanism, that understands web concepts like URIs, hostnames, paths, and more. The Ingress concept lets you map traffic to different backends based on rules you define via the Kubernetes API.
- An API object that manages external access to the services in a cluster, typically HTTP.
- Ingress may provide load balancing, SSL termination and name-based virtual hosting.
- Ingress is frozen. New features are being added to the Gateway API.
- 인그레스 기능 : HTTP(서비스) 부하분산, 카나리 업그레이드
- 인그레스 컨트롤러 : 인그레스의 실제 동작 구현은 인그레스 컨트롤러(Nginx, Kong 등)가 담당
- 인그레스 + 인그레스 컨트롤러(Nginx) 기능 : HTTP(서비스) 부하분산, 카나리 업그레이드, HTTPS 처리(TLS 종료)
2. Nginx 인그레스 컨트롤러 설치
인그레스(Ingress) 소개 : 클러스터 내부의 HTTP/HTTPS 서비스를 외부로 노출(expose)
인그레스 컨트롤러 : 인그레스의 실제 동작 구현은 인그레스 컨트롤러(Nginx, Kong 등)가 처리
- 쿠버네티스는 Ingress API 만 정의하고 실제 구현은 add-on에 맡김
- Ingress-Nginx Controller -> 간편한 테스트를 위해서 NodePort 타입(externalTrafficPolicy:Local) 설정
- 다양한 Nginx 인그레스 컨트롤러 인입 방법
- MetalLB 사용, Via the host network 사용, Using a self-provisioned edge 사용, External IPs 사용
▶ Ingress NGINX Controller for Kubernetes
- ingress-nginx is an Ingress controller for Kubernetes using NGINX as a reverse proxy and load balancer.
- How it works : configmap 설정을 nginx config에 적용(by lua), 변경 시 (최소) reload
- The goal of this Ingress controller is the assembly of a configuration file (nginx.conf).
- The main implication of this requirement is the need to reload NGINX after any change in the configuration file.
- Though it is important to note that we don't reload Nginx on changes that impact only an upstream configuration (i.e Endoints change when you deploy your app)
- We use lua-nginx-module to achieve this. Check below to learn more about how it's done.
- When a reload is required
- New Ingress Resource Created.
- TLS section is adde dto existing Ingress.
- Change in Ingress annotations that impacts more than just upstream configuration. For instance load-balance annotation does not require s reload.
- A path is added/removed from an Ingress.
- An Ingress, Service, Secret is removed.
- Some missing referenced object from the Ingress is available, like a Service or Secret.
- A Secret is updated.
▶ Ingress-Nginx 컨트롤러 생성
▶ kubectl krew 설치
3. 인그레스(Ingress) 실습 및 통신 흐름 확인
실습 구성도
- 컨트롤플레인 노드에 인그레스 컨트롤러(Nginx) 파드를 생성, NodePort로 외부에 노출
- 인그레스 정책 설정 : Host/Path routing, 실습의 편리를 위해서 도메인 없이 IP로 접속 설정 가능
3.1 디플로이먼트와 서비스를 생성
▶ 생성 및 확인
3.2 인그레스(정책) 생성
▶ 인그레스 생성 및 확인
3.3 인그레스를 통한 내부 접속
- Nginx 인그레스 컨트롤러를 통한 접속(HTTP 인입) 경로 : 인그레스 컨트롤러 파드에서 서비스 파드의 IP로 직접 연결
▶ URI(Uniform Resource Identifier, RFC3986)
- Request URI는 서버 주소나 파일 이름, 파라미터 등 다양한 리소스를 식별하기 위해 사용하는 문자열입니다
- 절대 URI(absolute URI, 필요한 모든 정보를 기술)와 상태 URI(relative URI, 상대적인 위치)가 있습니다.
- 스킴이름 // 서버 주소 : 포트 번호 / 파일 경로 ? 쿼리 문자열 # 프래그먼트 식별자
▶ X-Forwarded-For 헤더, X-Forwarded-Proto 헤더
- X-Forwarded-For 헤더는 송신지 IP 주소가 변환되는 환경(장비, 서버, 솔루션 등)에서, 변환 전 송신지(클라이언트) IP 주소를 저장하는 헤더입니다
- X-Forwarded-Proto 헤더는 변환 전 프로토콜을 저장합니다 (예. SSL Offload 환경에서 서버 측에서 클라이언트가 요청 시 사용한 원래 프토로콜을 확인)
▶ Client IP를 가져오는 방법
- 웹 애플리케이션이 client IP를 추출하기 위해서 Http request header를 다음과 같은 순서로 뒤짐
1. Proxy-Client-IP : 특정 웹 어플리케이션에서 사용 (예. WebLogic Connector - mod_wl)
2. WL-Proxy-Client-IP : 특정 웹 어플리케이션에서 사용 (예. WebLogic Connector - mod_wl)
3. X-Forwarded-For : HTTP RFC 표준에는 없지만 사실상 표준
4. request.getRemoteAddr()
5. CLIENT_IP - 3번 X-Forwarded-For : <client>, <proxy1>, <proxy2>
요청이 여러 프록시를 거치는 경우 X-Forwarded-For 요청 헤더의 clientIPAddress 다음에는 로드 밸런서에 도달하기 전에 요청이 통과하는 각 연속 프록시의 IP 주소가 온다.
따라서, 가장 오른쪽의 IP 주소는 가장 최근의 프록시의 IP주소이고 가장 왼쪽의 IP 주소는 원래 클라이언트의 IP 주소이다.
▶ (중요!)인그레스(Nginx 인그레스 컨트롤러)를 통한 접속(HTTP 인입) 확인 : HTTP 부하분산 & PATH 기반 라우팅, 애플리케이션 파드에 연결된 서비스는 Bypass
- Nginx 파드가 endpoint 정보 등을 모니터링 가능한 이유 : 클러스터롤과 롤(엔드포인트 list, watch)를 바인딩된 서비스 어카운트를 파드가 사용!
- 파드는 외부 클라이언트의 IP 획득을 위해서 X-Forwarded-For(XFF)를 참조 해야한다!
3.5 Nginx 분산 알고리즘 변경
▶ nginx는 기본 RR 라운드 로빈이지만, IP-Hash나 Session Cookie 설정으로 대상 유지 가능
[참고] AWS Ingress (ALB) 모드
- 인스턴스 모드 : AWS ALB(Ingress)로 인입 후 각 워커노드의 NodePort로 전달 후 IPtables 룰(SEP)에 따라 파드로 분배
- IP 모드 : nginx ingress controller 동작과 유사하게 AWS LoadBalancer Controller 파드가 kube api를 통해서 파드의 IP를 제공받아서 AWS ALB에 타겟(파드 IP)를 설정
3.6 Host 기반 라우팅
▶ 인그레스 생성 및 확인
▶ 인그레스(Nginx 인그레스 컨트롤러)를 통한 접속(HTTP 인입) 확인