파드는 일시적이다. 파드가 다른 파드를 위한 공간을 확보하려고 노드에서 제거되거나, 누군가 파드 수를 줄이거나, 클러스터 노드의 장애로 언제든 다른 노드로 이동할 수 있다.
쿠버네티스는 노드에 파드를 스케줄링한 후 파드가 시작되기 바로 전에 파드의 IP 주소를 할당한다. 클라이언트는 서버인 파드의 IP 주소를 미리 알 수 없다.
수평 스케일링은 여러 파드가 동일한 서비스를 제공할 수 있음을 의미, 각 파드는 고유한 IP 주소가 있다. 모든 파드는 단일 IP 주소로 액세스할 수 있어야 한다.
쿠버네티스의 서비스는 동일한 서비스를 제공하는 파드 그룹에 지속적인 단일 접점을 만들려고 할 때 생성하는 리소스
각 서비스는 서비스가 존재하는 동안 절대 바뀌지 않는 IP 주소와 포트가 있다.
클라이언트는 해당 IP와 포트로 접속한 다음 해당 서비스를 지원하는 파드 중 하나로 연결
서비스 연결은 서비스 뒷단의 모든 파드로 로드밸런싱된다.
기본 서비스 생성 yaml
apiVersion: v1
kind: Service
metadata:
name: kubia
spec:
ports:
- port: 80 #서비스가 사용할 포트
targetPort: 8080 #서비스가 포워드할 컨테이너 포트
selector: # app=kubia 레이블이 있는 모든 파드가 이 서비스에 포함
app: kubia
서비스 조회 : kubectl get svc
서비스의 기본 목적은 파드 그룹을 클러스터의 다른 파드에 노출시키는 것이지만, 대개 서비스를 외부로 노출하기를 원한다.
실행 중인 컨테이너에 원격으로 명령어 실행 kubectl exec kubia-7nog1 -- curl -s http://10.111.249.153
명령어의 더블 대시는 kubectl 명령줄 옵션의 끝을 의미. 더블 대시 뒤의 모든 것은 파드 내에서 실행돼야 하는 명령
curl은 HTTP 요청을 서비스 IP로 보냄
쿠버네티스 서비스 프록시가 연결을 가로채서 세 개의 파드 중 임의의 파드로 요청을 전달
해당 파드 내에서 실행 중인 app은 요청을 처리하고 해당 파드의 이름을 포함하는 HTTP 응답을 반환
curl은 표준 출력으로 응답을 출력하고
kubectl이 있는 로컬 시스템의 표준 출력에 다시 표시
특정 클라이언트의 모든 요청을 매번 같은 파드로 리디렉션하려면 서비스의 세션어피니티 속성을 기본값 None 대신 ClientIP로 설정 필요
파드 컨테이너 내부의 DNS resolver가 구성돼 있기 때문에 네임스페이스와 svc.cluster.local 접미사를 생략할 수 있다.
서비스 IP에 핑을 할 수 없는 이유
서비스로 curl은 동작하지만 핑은 응답이 없는 이유는, 서비스의 클러스터 IP가 가상 IP이므로 서비스 포트와 결합된 경우에만 의미 있다.
서비스 엔드포인트
서비스는 파드에 직접 연결되지 않고, 엔드포인트 리소스가 그 사이에 있다.
kmg48801@cloudshell:~ (kubers-368504)$ kubectl describe svc kubia-loadbalancer
Name: kubia-loadbalancer
Namespace: default
Labels: <none>
Annotations: cloud.google.com/neg: {"ingress":true}
Selector: app=kubia
Type: LoadBalancer
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.1.1.160
IPs: 10.1.1.160
LoadBalancer Ingress: 34.64.123.50
Port: <unset> 80/TCP
TargetPort: 8080/TCP
NodePort: <unset> 31697/TCP
Endpoints: 10.0.128.28:8080,10.0.128.29:8080,10.0.128.30:8080
Session Affinity: None
External Traffic Policy: Cluster
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal EnsuringLoadBalancer 2m43s service-controller Ensuring load balancer
Normal EnsuredLoadBalancer 107s service-controller Ensured load balancer
엔드포인트 리소스는 서비스로 노출되는 파드의 IP 주소와 포트 목록
엔드포인트 리소스는 다른 쿠버네티스 리소스와 유사하므로 kubectl get으로 정보를 가져올 수 있다.
파드 셀렉터는 IP와 포트 목록을 작성하는 데 사용되며 엔드포인트 리소스에 저장된다.
클라이언트가 서비스에 연결하면 서비스 프록시는 이들 중 하나의 IP와 포트 쌍을 선택하고 들어온 연결을 대상 파드의 수신 대기 서버로 전달
서비스 엔드포인트 수동 구성
서비스의 엔드포인트를 서비스와 분리하면 엔드포인트를 수동으로 구성하고 업데이트 가능
파드 셀렉터 없이 서비스를 만들면 쿠버네티스는 엔드포인트 리소스를 만들지 못한다.
엔드포인트 생성 yaml
apiVersion: v1
kind: Endpoints
metadata:
name: external-service # 엔드포인트 오브젝트의 이름은 서비스 이름과 일치해야함
subsets:
- addresses:
- ip: 11.11.11.11 # 서비스가 연결 전달한 엔드포인트 IP
- ip: 22.22.22.22
ports:
- port: 80 # 엔드포인트 대상 포트
엔드포인트는 별도의 리소스이고, 서비스 속성이 아니다.
셀렉터가 없는 서비스의 서비스 이름은 엔드포인트 오브젝트 이름과 동일해야 한다.
외부 서비스를 위한 별칭
외부 서비스의 별칭으로 사용되는 서비스를 만들려면 유형 필드를 ExternalName으로 설정해야 한다.
서비스가 생성되면 파드는 서비스의 FQDN을 사용하는 대신 external-service.default.svc.cluster.local 도메인 이름으로 외부 서비스에 연결할 수 있다.
ExternalName 서비스는 DNS 레벨에서만 구현된다.
외부 서비스 yaml
apiVersion: v1
kind: Service
metadata:
name: external-service
spec:
type: ExternalName # 서비스 유형을 ExternalName으로 설정
externalName: someapi.somecompany.com #실제 서비스의 정규화된 도메인 이름 (FQDN)
ports:
- port: 80
외부 클라이언트에 서비스 노출
노드포트로 서비스 유형 설정 : 노드포트 서비스의 경우 각 클러스터 노드는 노드 자체에서 포트를 열고 해당 포트로 수신된 트래픽을 서비스로 전달
서비스는 내부 클러스터 IP와 포트로 액세스할 수 있을 뿐만 아니라 모든 노드의 전용 포트로도 액세스 가능
서비스 유형을 로드밸런서로 설정 : 쿠버네티스가 실행 중인 클라우드 인프라에서 프로비저닝된 전용 로드밸런서로 서비스에 액세스할 수 있다. 로드밸런서는 트래픽을 모든 노드의 노드포트로 전달한다.
인그레스 리소스 생성 : HTTP 레벨에서 작동하고 하나의 IP + Path Routing 방식
노드포트 서비스
파드 세트를 외부 클라이언트에 노출시키는 첫 번째 방법은 서비스를 생성하고, 유형을 노드포트로 설정하는 것
노드포트 서비스를 만들면 쿠버네티스는 모든 노드에 특정 포트를 할당하고 서비스를 구성하는 파드로 들어오는 연결을 전달한다.
노드포트 서비스 yaml
apiVersion: v1
kind: Service
metadata:
name: kubia-nodeport
spec:
type: NodePort # 서비스 유형을 노드포트로 설정
ports:
- port: 80 # 서비스 내부 클러스터 IP 포트
targetPort: 8080 #서비스 대상 파드의 포트
nodePort: 30123 #각 클러스터 노드의 포트 30123으로 서비스에 액세스 가능
selector:
app: kubia
nodePort를 생략하면 쿠버네티스가 임의의 포트를 선택한다.
노드포트로 서비스에 액세스하려면 해당 노드포트에 대한 외부 연결을 허용하도록 방화벽을 구성해야 한다.
외부 로드밸런서로 서비스 노출
로드밸런서는 공개적으로 액세스 가능한 고유한 IP 주소를 가지며 모든 연결을 서비스로 전달
로드밸런서 서비스는 노드포트 서비스의 확장이다.
로드밸런서 서비스 yaml
apiVersion: v1
kind: Service
metadata:
name: kubia-loadbalancer
spec:
type: LoadBalancer # 이 유형의 서비스는 쿠버네티스 클러스터를 호스팅하는 인프라에서 로드밸런서를 얻는다.
ports:
- port: 80
targetPort: 8080
selector:
app: kubia
서비스를 생성한 후 클라우드 인프라가 로드밸런서를 생성하고 IP 주소를 서비스 오브젝트에 쓰는 데 시간이 걸리기에, External IP는 즉각적으로 생기지 않는다.
외부 연결의 특성 이해
외부의 연결을 수신한 노드에서 실행 중인 파드로만 외부 트래픽을 전달하도록 서비스를 구성해 네트워크 홉을 줄일 수 있다. (선택된 노드에 존재하는 파드로만 연결)
서비스의 스펙 섹셕의 externalTrafficPolicy 필드를 Local로 설정하면 된다.
서비스 정의에 이 설정이 포함돼 있고 서비스의 노드포트로 외부 연결이 열린 경우 서비스 프록시는 로컬에 실행 중인 파드를 선택한다.
로컬 파드가 존재하지 않으면 연결이 중단된다.
클러스터 내의 클라이언트가 서비스로 연결할 때 서비스의 파드는 클라이언트의 IP 주소를 얻을 수 있는데, 노드포트로 연결을 수신하면 패킷에서 소스 네트워크 주소 변환이 수행되므로 패킷의 소스 IP가 변경된다.
인그레스
인그레스는 한 IP 주소로 수십 개의 서비스에 접근이 가능하도록 지원해준다.
클라이언트가 HTTP 요청을 인그레스에 보낼 때, 요청한 호스트와 경로에 따라 요청을 전달할 서비스가 결정된다.
인그레스는 네트워크 스택의 7계층이므로 서비스가 할 수 없는 쿠키 기반 세션 어피니티 등과 같은 기능을 제공한다.
인그레스 리소스를 작동시키려면 클러스터에 인그레스 컨트롤러를 실행해야 한다.
minikube에서는 애드온 활성화 -> minikube addons enable ingress
인그레스 생성 시 주의할 점으로는 default Backend 설정을 안하면 404 ERROR를 받는다는 것 (기본 백엔드를 지정하지 않으면 GKE은 404를 반환하는 기본 백엔드를 제공합니다. 이것은 kube-system 네임스페이스의 클러스터에 default-http-backend NodePort 서비스로 생성됩니다.)
apiVersion: v1
kind: Service
metadata:
name: kubia-nodeport
spec:
type: NodePort # 서비스 유형을 노드포트로 설정
ports:
- port: 80 # 서비스 내부 클러스터 IP 포트
targetPort: 8080 #서비스 대상 파드의 포트
selector:
app: kubia
클라이언트는 kubia.example.com의 DNS 조회 수행
DNS서버가 인그레스 컨트롤러의 IP를 반환
클라이언트는 HTTP 요청을 인그레스 컨트롤러로 전송하고 헤더에 kubia.example.com 지정
컨트롤러는 해당 헤더에서 클라이언트가 액세스하려는 서비스를 결정
서비스와 관련된 엔드포인트 오브젝트로 파드 IP 조회
클라이언트 요청을 파드에 전달
하나의 인그레스로 여러 서비스를 노출할 수도 있다.
TLS 트래픽 처리용 인그레스 구성
TLS 연결을 하게 되면 클라이언트와 컨트롤러 간의 통신은 암호화되지만, 컨트롤러와 백엔드 파드 간의 통신은 암호화되지 않는다.
파드가 웹 서버를 실행하는 경우 HTTP 트래픽만 허용하고, 인그레스 컨트롤러가 TLS와 관련된 모든 것을 처리하도록 구성
서비스
파드는 일시적이다. 파드가 다른 파드를 위한 공간을 확보하려고 노드에서 제거되거나, 누군가 파드 수를 줄이거나, 클러스터 노드의 장애로 언제든 다른 노드로 이동할 수 있다.
쿠버네티스는 노드에 파드를 스케줄링한 후 파드가 시작되기 바로 전에 파드의 IP 주소를 할당한다. 클라이언트는 서버인 파드의 IP 주소를 미리 알 수 없다.
수평 스케일링은 여러 파드가 동일한 서비스를 제공할 수 있음을 의미, 각 파드는 고유한 IP 주소가 있다. 모든 파드는 단일 IP 주소로 액세스할 수 있어야 한다.
쿠버네티스의 서비스는 동일한 서비스를 제공하는 파드 그룹에 지속적인 단일 접점을 만들려고 할 때 생성하는 리소스
각 서비스는 서비스가 존재하는 동안 절대 바뀌지 않는 IP 주소와 포트가 있다.
클라이언트는 해당 IP와 포트로 접속한 다음 해당 서비스를 지원하는 파드 중 하나로 연결
서비스 연결은 서비스 뒷단의 모든 파드로 로드밸런싱된다.
기본 서비스 생성 yaml
서비스 조회 :
kubectl get svc
서비스의 기본 목적은 파드 그룹을 클러스터의 다른 파드에 노출시키는 것이지만, 대개 서비스를 외부로 노출하기를 원한다.
실행 중인 컨테이너에 원격으로 명령어 실행
kubectl exec kubia-7nog1 -- curl -s http://10.111.249.153
curl은 HTTP 요청을 서비스 IP로 보냄
쿠버네티스 서비스 프록시가 연결을 가로채서 세 개의 파드 중 임의의 파드로 요청을 전달
해당 파드 내에서 실행 중인 app은 요청을 처리하고 해당 파드의 이름을 포함하는 HTTP 응답을 반환
curl은 표준 출력으로 응답을 출력하고
kubectl이 있는 로컬 시스템의 표준 출력에 다시 표시
특정 클라이언트의 모든 요청을 매번 같은 파드로 리디렉션하려면 서비스의 세션어피니티 속성을 기본값 None 대신 ClientIP로 설정 필요
서비스 프록시는 동일한 클라이언트 IP의 모든 요청을 동일한 파드로 전달
쿠버네티스는 None과 ClientIP라는 두 가지 유형의 서비스 세션 어피니티만 지원
세션 어피니티 서비스 생성 yaml
멀티 포트 서비스 생성 yaml
서비스 검색
환경변수를 통한 서비스 검색
kubectl exec kubia-3inly env
서비스 IP에 핑을 할 수 없는 이유
서비스 엔드포인트
서비스 엔드포인트 수동 구성
엔드포인트 생성 yaml
외부 서비스를 위한 별칭
외부 서비스 yaml
외부 클라이언트에 서비스 노출
노드포트 서비스
노드포트 서비스 yaml
외부 로드밸런서로 서비스 노출
로드밸런서 서비스 yaml
외부 연결의 특성 이해
인그레스
minikube addons enable ingress
인그레스 생성 yaml (교재대로 하면 안됨)
인그레스에서 사용할 서비스 yaml
TLS 트래픽 처리용 인그레스 구성
openssl genrsa -out tls.key 2048
openssl req -new -x509 -key tls.key tls.key -out tls.cert -days 360 -subj /CN=kubia.example.com
kubectl create secret tls tls-secret --cert=tls.cert --key=tls.key
TLS 트래픽 처리용 인그레스
레디니스 프로브
레디니스 프로브 동작
레디니스 프로브를 가진 레플리카셋 (교재에서는 레플리케이션컨트롤러로 했지만, 레플리케이션컨트롤러는 이제 안쓰이기 때문에 replicaset으로 실습 진행)
kubectl exec kubia-fh46k -- touch /var/ready
명령어 수행 -> 2번째 파드만 READY 됨서비스 문제 해결
요약
쿠버 치트 history