Service
- 외부에서 사용자가 Application Pod에 접근할 수 있도록 하는 k8s Object.
- 클라이언트의 요청을 받고 pod에게 로드밸런싱으로 트래픽을 전달하는 역할도 겸한다.
- 실제로 사용자 (클라이언트)가 사용하게 될 ip주소와 Port가 Endpoint.
Service Types
- Service에는 여러 타입이 있고, 각 타입마다 애플리케이션을 어떻게 / 어디로 expose 시킬 것인지의 Rule이 조금씩 다름.
- Service Type의 디폴트는 ClusterIP. CKA에는 LoadBalancer와 ExternalName도 범위에 들어간다고 함
ClusterIP
- 클러스터 내에서 Pod끼리 통신하고자 할 때 사용. 클러스터 외부 노출이 아니라 클러스터 내부에서의 노출임.
- 즉 Same cluster & different Namespace일 때 사용 가능함.
- frontend / backend 서비스가 같은 클러스터에 있다고 가정하면
- 클라이언트에 해당하는 frontend pod가 backend Service에 request
- backend Service는 각 pod로 트래픽 로드 밸런싱 수행
NodePort
- 클러스터 외부와 연결할 수 있도록 ip와 포트를 노출하는 역할. 클러스터 외부의 클라이언트는 nodePort를 통해 클라이언트에 요청을 날릴 수 있다.
LoadBalancer
- 클러스터 외부와 연결할 수 있도록 ip와 포트를 노출하지만, Cloud Load balancer를 필요로 하는 객체.
- 즉 public cloud 위에서 k8s가 돌고 있으며, 해당 cloud provider가 로드 밸런서를 지원하고 있을 때 사용 가능.
- AWS나 GCP, Azure 등의 클라우드 벤더에서 사용 가능함
- k8s가 로드 밸런서를 생성한 뒤 클러스터의 service로 붙이는 개념.
ExternalName service는 LoadBalancer와 거의 비슷함. CName을 설정해서 해당 이름으로 LoadBalancer에 바로 접근할 수 있는 게 차이점.
먼저 Deployment부터 생성해 준다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-server
labels:
app: frontend
spec:
replicas: 3
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
- ClusterIP Service
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
type: ClusterIP
selector:
app: frontend # 어떤 pod의 Service 역할을 할지 지정하는 것.
ports:
- protocol: TCP
port: 80
targetPort: 8080
이렇게 두 개를 kubectl에 apply했을 경우, Service의 상세정보에서 Endpoint를 확인해보면
- pod의 ip주소 + clusterIP에서 정의한 targetPort
형태로 정의되어 있는 걸 볼 수 있다.
cf. ClusterIP 형태로 service를 정의했기 때문에, 클러스터 외부에서 해당 ip주소로 요청을 보낼 수 없다.
아래의 pod는 clusterIP의 작동여부를 직접 확인하기 위해 우회용 pod를 생성한 것.
apiVersion: v1
kind: Pod
metadata:
name: pod-svc-test
spec:
containers:
- name: busybox
image: radial/busyboxplus:curl
command:
- sleep
- '3600'
- 해당 pod을 실행하는 식으로 -
kubectl exec pod-svc-test -- curl nginx-service:80
실행하면 제대로 nginx 결과를 리턴한다.
NodePort를 사용해서 클러스터 외부에서도 접근 가능하도록 service 생성하기.
apiVersion: v1
kind: Service
metadata:
name: nginx-service-nodeport
spec:
type: NodePort
selector:
app: frontend
ports:
- protocol: TCP
port: 80
targetPort: 80 # 컨테이너가 80포트에서 실행중이므로 80
nodePort: 30099
# 반드시 5 digit을 사용해야 한다. define IP to the Service.
localhost:30090으로 접근하면 nginx로 연결되는 것을 확인할 수 있다.
- Cluster IP(master / worker node)로도 접근 가능하다.
- 단 AWS 인스턴스를 사용했을 경우 Inbound Rule이 설정되어 있어야 하고, GCP의 경우 Security Group이 인터넷 접근을 허용해야 한다.
Discover k8s Service
- k8s는 기본적으로 DNS 서비스를 제공한다. 클러스터에 있는 애플리케이션에 쉽게 접근할 수 있도록.
- fqDN의 경우 해당 Service의 어느 namespace라도 접근할 수 있다.
- 동일한 namespace 내의 pod를 호출할 경우 service name 도메민만으로도 호출이 가능함.
클러스터 내부 (pod-svc-test)에서 service로 접근하려면
- kubectl 커맨드로 <서비스명>:<포트명> (
nginx-service:8080
) 을 사용할 수 있었다.
DNS pod를 새로 생성하면
apiVersion: v1
kind: Pod
metadata:
name: svc-test-dns
namespace: service-namespace # 별도의 namespace에 pod 생성
spec:
containers:
- name: busybox-svc
image: radial/busyboxplus:curl
command:
- sleep
- '3600'
이전에 정의한 nginx-service와 namespace가 다르기 때문에, kubectl exec 커멘드를 그대로 사용하면 에러가 발생한다.
kubectl exec -n service-namespace svc-test-dns -- curl nginx-service.default.svc.cluster.local:8080
- namespace 명시, 호출하려는 서비스의 fqdn를 명시할 경우 정상적으로 호출이 가능하다.
Manage Service in k8s - ingress Controller
Pod로 들어오는 모든 트래픽을 Ingress라고 부른다. ingress가 있을 경우
- 클라이언트의 모든 요청은 일단 ingress로 넘어간다
- ingress에서 service(s)로 트래픽을 넘겨준다.
물론 nodePort나 LoadBalancer Service를 사용할 수도 있으나,
ingressController에서는 추가적으로 여러 기능을 지원한다.
- Abstract interface 제공
- More Secure Traffic
- Additional Functionality 제공. (SSL Termination, Load balancing, Namebase Virtual Hosting)
cf. NameBase Virtual Hosting: 서로 다른 service별로 resource / pod를 할당해주는 기능
ingress Controller의 개수는 제한이 없다.
- ingress별로 rule을 정의할 수 있으며, 해당 rule에 대응되는 backend로 트래픽을 routing.
- 예시에서는 http path을 기준으로 정함.
cf. service의 name 필드도 nginx-port로 정의해야 한다.
- NamedPort. Service 내에서 Port의 이름을 지정할 수 있다.
- service에서 port 정의하는 부분에 name을 지정하고, ingress의 backend 정의하는 영역에 해당 name을 지정하면 된다.
- 이렇게 정의하면, rule에서 protocol / port번호 등을 굳이 지정할 필요가 없게 됨. service에서 정의한 부분을 가져와 쓰면 되기 때문
즉 각 객체가 담당하는 영역 / 통신하는 상대방은 다음과 같다.
Ingress -> Service. Service -> Deployment.
- 먼저 nginx의 Deployment를 생성한다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-official-deployment
spec:
replicas: 1
selector:
matchLabels:
app: nginx-official
template:
metadata:
labels:
app: nginx-official
spec:
containers:
- name: nginx-official
image: 'nginx:latest'
ports:
- containerPort: 8080
- Service를 생성한다.
apiVersion: v1
kind: Service
metadata:
name: nginx-official-service
spec:
type: NodePort # aws나 gcp같은 클라우드 벤더사라면 LoadBalancer를 사용할 수 있다.
ports:
- protocol: TCP
port: 80 # service가 접근할 Port
nodePort: 31303 # 외부에 노출할 port
selector:
app: nginx-official # deployment의 app 필드와 일치.
- 또다른 종류의 Deployment, Service를 생성한다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: magicalnginx-deployment
spec:
replicas: 1
selector:
matchLabels:
app: magical-nginx
template:
metadata:
labels:
app: magical-nginx
spec:
containers:
- name: magical-nginx
image: 'anshuldevops/magicalnginx:latest' # custom image 생성.
ports:
- name: nginx-port
containerPort: 3000
apiVersion: v1
kind: Service
metadata:
name: magical-nginx
spec:
type: NodePort
ports:
- protocol: TCP
port: 80
nodePort: 31304
name: http
selector:
app: magical-nginx # selector를 새로 생성한 Deployment로 정의한다.
결과
여기에 IngressController를 붙이면
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-rules
spec:
rules:
- host: nginx-official.example.com # 해당 호스트로 접근했을 경우 nginx-official-service로 접근
http:
paths:
- path: /
pathType: Exact
backend:
service:
name: nginx-official-service
port:
number: 80
- host: magical-nginx.example.com # 해당 호스트로 접근했을 경우 magical-nginx로 접근
http:
paths:
- path: /
pathType: Exact
backend:
service:
name: magical-nginx
port:
number: 80
host가 정상적으로 등록되어 있다.
ip주소와 host명을 붙여서 호출하면, 정상적으로 작동되는 것을 확인할 수 있다.
'학습일지 > kubernetes' 카테고리의 다른 글
CKA 대비 kubernetes 스터디 - 1. Core Concept (0) | 2022.02.25 |
---|---|
Kubernetes Deep Dive - (8). Storage (0) | 2021.10.09 |
Kubernetes Deep Dive - (6). Network (0) | 2021.10.02 |
Kubernetes Deep Dive - (5). Deployment (0) | 2021.09.30 |
Kubernetes Deep Dive - (4). Pods and Containers (0) | 2021.09.26 |