반응형
Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
Tags
- @Data
- kubenetes
- 가장 큰 수
- 모던 자바 인 액션
- 영속 자료구조
- 완주하지 못한 선수
- 롬복 어노테이션
- 알고리즘
- 커링
- @Setter
- @EnableScheduling
- 크론 표현식
- 코딩 테스트
- 기능개발
- 검색 기능 확장
- 스프링 스케쥴러
- 프로그래머스
- 해시
- 루씬 인 액션
- 스택/큐
- 정렬
- @Getter
- K번째수
- 전화번호 목록
- 다리를 지나는 트럭
- H-index
- @configuration
- 쿠버네티스
- Java
- 고차원 함수
Archives
- Today
- Total
Today I Learned
[쿠버네티스 인 액션] 5. 서비스: 클라이언트가 파드를 검색하고 통신을 가능하게 함 (1) 본문
728x90
5장에서 다루는 내용
- 단일 주소로 파드를 노출하는 서비스 리소스 만들기
- 클러스터 안에서 서비스 검색
- 외부 클라이언트에 서비스 노출
- 클러스터 내에서 외부 서비스 접속
- 파드가 서비스할 준비가 됐는지 제어하는 방법
- 서비스 문제 해결
- 일반적으로 시스템 관리자가 클라이언트 구성 파일에 서비스를 제공하는 서버의 정확한 IP 주소나 호스트 이름을 지정해 각 클라이언트 애플리케이션을 구성한다.
- 하지만 쿠버네티스에서 동일한 작업을 수행하면 다음과 같은 이유로 동작하지 않는다.
- 파드는 일시적이다. 파드는 언제든 늘어나거나 줄어들거나 이동할 수 있다.
- 노드에 파드를 스케줄링한 후 파드가 시작되기 바로 전에 파드의 IP 주소를 할당한다. 클라이언트는 서버인 파드의 IP 주소를 미리 알 수 없다.
- 수평 스케일링은 여러 파드가 동일한 서비스를 제공할 수 있음을 의미한다. 클라이언트는 서비스를 지원하는 파드의 수와 개별 IP에 상관 없이 모든 파드에 단일 IP 주소로 엑세스할 수 있어야 한다.
5.1 서비스 소개
- 쿠버네티스의 서비스는 동일한 서비스를 제공하는 파드 그룹에 지속적인 단일 접점을 만들기 위한 리소스이다.
- 각 서비스는 변경되지 않는 IP 주소와 포트가 있으며, 클라이언트는 해당 IP와 포트로 접속한 다음 해당 서비스를 지원하는 파드 중 하나로 연결된다.
예제를 통한 서비스 설명
- 프론트엔드 웹서버와 백엔드 데이터베이스 서버 예제에서 프론트엔드 역할을 하는 파드는 여러 개 있을 수 있지만, 백엔드 데이터베이스는 하나만 있을 것이다.
- 시스템이 기동하려면 두 가지 문제를 해결해야 한다.
- 웹 서버 수에 상관 없이 외부 클라이언트는 프론트엔드 파드에 연결할 수 있어야 한다.
- 프론트엔드 파드는 벡엔드 데이터베이스에 연결해야 한다. 데이터베이스는 파드 내에서 실행되므로 시간이 IP 주소가 변경될 수 있고, 프론트엔드와의 연결을 유지해야 한다.
- 프론트엔드 파드와 백엔드 파드 각각에 대한 서비스를 생성해서 안정적인 주소를 만들어야 한다.
5.1.1 서비스 생성
- 서비스 연결은 서비스 뒷단의 모든 파드로 로드밸런싱된다.
- 레이블 셀렉터를 통해 정확히 어떤 파드가 서비스의 일부분인지 정의한다.
kubectl expose로 서비스 생성
- expose 명령어는 레플리케이션컨트롤러에서 사용된 것과 동일한 파드 셀렉터를 사용해 서비스 리소스를 생성하고 모든 파드를 단일 IP와 포트로 노출한다.
YAML 디스크립터를 통한 서비스 생성
- kubernetes API 서버에 YAML을 게시해 서비스를 수동으로 생성할 수도 있다.
apiVersion: v1
kind: Service
metadata:
name: kubia
spec:
ports:
- port: 80 # 서비스가 사용할 포트
targetPort: 8080 # 서비스가 포워드할 컨테이너 포트
selector:
app: kubia # app=kubia 레이블이 있는 모든 파드가 이 서비스에 포함
새 서비스 검사하기
- YAML을 게시한 후 네임스페이스의 모든 서비스 리소스를 호죄하고 서비스에 내부 클러스터 IP가 할당됐는지 확인할 수 있다.
- 할당된 주소는 클러스터 IP 이므로 클러스터 내부에서만 엑세스할 수 있다.
클러스터 내에서 서비스 테스트
- 몇 가지 방법으로 클러스터 내에서 서비스 요청을 보낼 수 있다.
- 서비스의 클러스터 IP로 요청을 보내고 응답을 로그로 만드는 파드를 만든다.
- 쿠버네티스 노드로 ssh 접속하고 curl 명령을 실행한다.
- kubectl exec 명령어로 기존 파드에서 curl 명령을 실행한다.
실행중인 컨테이너에 원격으로 명령어 실행
- kubectl exec 명령어로 기존 파드의 컨테이너 내에서 원격으로 임의의 명령어를 실행할 수 있으며, 컨테이너의 내용, 상태, 환경을 검사할 때 유용하다.
- kubectl get pods 명령어로 파드를 조회할 수 있고, kubecl get svc 명령어로 서비스의 클러스터 IP를 알 수 있다.
$kubectl exec kubia-9g9xb -- curl -s http://10.96.4.219
- 명령을 실행하면 파드의 컨테이너 내에서 curl 명령을 실행하고, curl은 HTTP 요청을 서비스 IP로 보낸다.
- 쿠버네티스 서비스 프록시는 연결을 가로채서 서비스가 연결된 임의의 파드 중 하나로 요청을 전달하고 응답을 반환한다.
- curl은 표준 출력으로 응답을 출력하고 이를 kubectl이 있는 로컬 시스템의 표준 출력에 다시 표시한다.
서비스 세션 어피니티 구성
- 특정 클라이언트의 모든 요청을 매번 같은 파드로 리디렉션하려면 서비스의 세션 어피니티(sessionAffinity) 속성을 기본값 대신 ClientIP로 설정한다.
apiVersion: v1
kind: Service
metadata:
name: kubia
spec:
sessionAffinity: ClientIP
ports:
- port: 80
targetPort: 8080
selector:
app: kubia
- 세션어피니티는 None과 ClientIP 옵션만 지원하며, 쿠키 기반 세션 어피니티 옵션은 없다.
- 서비스는 TCP와 UDP 패킷을 처리하고 payload는 신경 쓰지 않기 때문에 HTTP 프로토콜의 구성인 쿠키를 알지 못하기 때문이다.
동일한 서비스에서 여러 개의 포트 노출
- 멀티 포트 서비스를 사용해서 단일 클러스터 IP로 모든 서비스 포트를 노출할수 있다.
- 예를 들어 파드가 두개의 포트(8080, 8443)을 수신한다면, 하나의 서비스를 사용해 포트 80과 443을 파드의 포트 8080과 8443으로 전달할 수 있다.
apiVersion: v1
kind: Service
metadata:
name: kubia
spec:
ports:
- name: http
port: 80
targetPort: 8080
- name: https
port: 443
targetPort: 8443
selector:
app: kubia
이름이 지정된 포트 사용
- 지금까지는 포트 번호를 참조해왔지만 각 파드의 포트에 이름을 지정하고 서비스 스펙에서 이름으로 참조할 수도 있다.
- 이렇게하면 서비스 스펙을 변경하지 않고도 포트 번호를 변경할 수 있다는 장점이 있다.
#파드 정의에 포트 이름 사용
kind: Pod
spec:
containers:
- name: kubia
ports:
- name: http
containerPort: 8080
- name: https
containerPort: 8443
#서비스에 이름이 정의된 포트 참조
apiVersion: v1
kind: Service
spec:
ports:
- name: http
port: 80
targetPort: http
- name: https
port: 443
targetPort: https
5.1.2 서비스 검색
- 쿠버네티스는 클라이언트 파드가 서비스의 IP와 포트를 검색할 수 있는 방법을 제공한다.
환경변수를 통한 서비스 검색
- 파드가 시작되면 쿠버네티스는 해당 시점에 존재하는 각 서비스를 가리키는 환경변수 세트를 초기화한다.
- 클라이언트 파드를 생성하기 전에 서비스를 생성하면 해당 파드의 프로세스는 환경변수를 검사해 서비스의 IP 주소와 포트를 얻을 수 있다.
- kubectl exec 명령을 사용해 파드에서 명령어를 실행할 수 있지만, 파드를 만든 후에 서비스를 만들면 서비스에 대한 환경변수를 설정할 수 없다.
- 서비스에 대한 환경변수를 보려면 먼저 모든 파드를 삭제하고 새로 파드를 만들어야 한다.
$kubectl delete po --all
- 이제 kubectl exec 명령으로 컨테이너 내부에서 env 명령어를 실행해 환경변수를 조회할 수 있다.
$kubectl exec kubia-6tbqr -- env
DNS를 통한 서비스 검색
- kube-system 네임스페이스에는 kube-dns 라는 파드가 있으며, 동일한 이름의 해당 서비스가 있다.
- 이 파드는 DNS 서버를 실행하며 클러스터에서 실행 중인 다른 모든 파드는 자동으로 이를 사용하도록 구성된다.
- 쿠버네티스 자체 DNS 서버에서 파드에서 실행중인 프로세스에서 수행된 모든 DNS 쿼리를 처리한다.
- 각 서비스는 내부 DNS 서버에서 DNS 항목을 가져오고 서비스 이름을 알고 있는 클라이언트 파드는 환경변수 대신 FQDN(정규화된 도메인 이름)으로 엑세스 할 수 있다.
FQDN을 통한 서비스 검색
- 프론트엔드-백엔드 예제에서 프론트엔드 파드는 다음 FQDN로 백엔드 데이터베이스 서비스에 연결할 수 있다.
backend-database.default.svc.cluster.local
- backend-database는 서비스 이름이고 default는 서비스가 정의된 네임스페이스, svc.cluster.local은 모든 클러스터의 로컬 서비스 이름에 사용되는 클러스터의 도메인 접미사다.
- 프론트엔드 파드가 벡앤드 파드와 동일한 네임스페이스에 있는 경우 svc.cluster.local 접미사와 네임스페이스는 생략할 수 있다.
따라서 서비스를 단순히 backend-database라 할 수 있다.
파드의 컨테이너 내에서 셸 실행
- kubectl exec 명령어에 -it 옵션을 사용해 파드의 컨테이너 내에서 bash를 실행할 수 있다.
- -it 은 --stdin(-i) 및 --tty(-t) 옵션을 사용하는 것과 동일하다. 이는 kubectl에게 터미널의 stdin 입력 스트림을 컨테이너(-i)로 라우팅하고 이를 TTY(-t)로 처리하도록 지시한다.
$kubectl exec -it kubia-6tbqr -- bash
- 이제 curl 명령어를 사용해 kubia 서비스에 엑세스할 수 있다.
- 각 파드 컨테이너 내부의 DNS resolver가 구성돼 있기 때문에 네임스페이스와 svc.cluster.local 접미사를 생략할 수 있다.
컨테이너의 /etc/resolv.conf 파일에서 확인할 수 있다.
서비스 IP에 핑을 할 수 없는 이유
- 서비스에 엑세스할 수 없는 경우 서비스 IP를 ping해 작동 여부를 확인하려 할 것이다.
- 서비스로 curl은 동작하지만 ping은 응답이 없는데, 서비스의 클러스터 IP가 가상 IP이므로 서비스 포트와 결합된 경우에만 의미가 있기 때문이다.
728x90
'쿠버네티스' 카테고리의 다른 글
[쿠버네티스 인 액션] 5. 서비스: 클라이언트가 파드를 검색하고 통신을 가능하게 함 (3) (0) | 2022.09.30 |
---|---|
[쿠버네티스 인 액션] 5. 서비스: 클라이언트가 파드를 검색하고 통신을 가능하게 함 (2) (0) | 2022.09.26 |
[쿠버네티스 인 액션] 4. 레플리케이션과 그 밖의 컨트롤러: 관리되는 파드 배포 (2) (0) | 2022.08.25 |
[쿠버네티스 인 액션] 4. 레플리케이션과 그 밖의 컨트롤러: 관리되는 파드 배포 (1) (0) | 2022.08.16 |
[쿠버네티스 인 액션] 3. 파드: 쿠버네티스에서 컨테이너 실행 (2) (0) | 2022.08.12 |
Comments