[CKA] kubernetes Service
동일한 기능을 구현하는 파드들을 하나의 진입점으로 접근 가능하도록 하는것이 서비스이다!
서비스는 4가지 타입이 있다.
타입 | 내용 |
ClusterIP(default) | 클러스터 내부에서만 사용가능한 IP 할당 받아 파드 통신 하는 서비스 |
NodePort | ClusterIP 기능 + 각 노드에 특정 포트로 통신 가능한 서비스 만약 노드에 IP가 외부에서 접속 가능하다면 Port 를 통해 외부 통신이 가능하다. |
LoadBalancer | 클러스터 외부에서 사용 가능한 IP 할당 받아 파드 통신 하는 서비스 외부 사용 가능한 IP는 로드밸런서 IP로 클라우드에 로드 밸런서를 자동으로 만들어져야 하여 클라우드 사용시에만 사용 가능 |
ExternalName | 클러스터 내부에서 외부 호출시 서비스 이름으로 통신 가능하도록 하는 서비스 내부 DNS에 외부 IP를 서비스명으로 설정하여 외부 통신 가능한 형태 |
각각 실습을 통해 알아보도록 하자!
Cluster IP 먼저 알아보자!
# deploy-nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy-nginx
spec:
replicas: 3
selector:
matchLabels:
app: webui
template:
metadata:
name: pod-nginx
labels:
app: webui
spec:
containers:
- name: my-nginx
image: nginx:1.14
해당 파드를 생성한다.
$ kubectl create -f deploy-nginx.yaml
이제 해당 파드를 관리하는 cluster ip 타입의 서비스를 만들어 보자!
# clusterip-nginx.yaml
apiVersion: v1
kind: Service
metadata:
name: clusterip-service
spec:
type: ClusterIP
clusterIP: 10.100.100.100
selector:
app: webui
ports:
- protocol: TCP
port: 80
targetPort: 80
해당 yaml을 생성한다.
$ kubectl create -f clusterip-nginx.yaml
service/clusterip-service created
서비스가 정상적으로 생성 되었는지 확인하면 서비스 IP 가 정의한대로 정상 생성 되었다.
$ kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
clusterip-service ClusterIP 10.100.100.100 <none> 80/TCP 91s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 40m
cluster ip 를 통해 서비스를 호출해보면 정상적으로 호출 된다.
$ curl 10.100.100.100
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
여기서 파드 밸런싱 되어 호출 되는지 확인을 위해 nginx ui 를 변경 해보도록 하자! 파드 3개 모두 접속하여 내용을 다르게 표기한다.
$ kubectl exec -it deploy-nginx-XX-XX -- bash
# cd /usr/share/nginx/html/
# ls
50x.html index.html
# echo "#1" > index.html
# cat index.html
#1
# exit
이제 다시 cluster ip를 호출해보면 계속 다른 파드로 접속 되는것을 알 수 있다. 라운드 로빈 방식이 아닌 부하에 따라 균등하게 호출 하는 방식이기에 순서가 정확하지 않다.
[node1 ~]$ curl 10.100.100.100
#3
[node1 ~]$ curl 10.100.100.100
#2
[node1 ~]$ curl 10.100.100.100
#1
[node1 ~]$ curl 10.100.100.100
#1
[node1 ~]$ curl 10.100.100.100
#3
[node1 ~]$ curl 10.100.100.100
#1
[node1 ~]$ curl 10.100.100.100
#1
[node1 ~]$ curl 10.100.100.100
#2
만약 파드수가 늘어나면 어떻게 될까? 3개에서 5개로 늘려보자!
$kubectl scale deployment deploy-nginx --replicas=5
deployment.apps/deploy-nginx scaled
서비스 상세정보를 보면 endpoint 가 5개로 자동 늘어났다. 여기서 알 수 있는점은 파드를 늘려도 service에서는 엔드포인트를 알아서 감지하여 해당하는 서비스를 찾아 호출하여 따로 관리하지 않아도 된다는 것이다.
[node1 ~]$ kubectl describe service clusterip-service
Name: clusterip-service
Namespace: default
Labels: <none>
Annotations: <none>
Selector: app=webui
Type: ClusterIP
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.100.100.100
IPs: 10.100.100.100
Port: <unset> 80/TCP
TargetPort: 80/TCP
Endpoints: 10.5.1.2:80,10.5.1.3:80,10.5.1.4:80 + 2 more...
다음 실습을 위해 다시 3개로 줄인다.
$ kubectl scale deployment deploy-nginx --replicas=3
deployment.apps/deploy-nginx scaled
이제 NodePort를 알아보자!
clusterip 형태에 각 노드에 Port 열리는기능이 추가 된 것이다.
각 노드는 노드 포트가 default 로 30000-32767 포트로 랜덤 할당 되어 열린다.
실습을 진행해보자!
# node-port.yaml
apiVersion: v1
kind: Service
metadata:
name: nodeport-service
spec:
type: NodePort
clusterIP: 10.100.100.200
selector:
app: webui
ports:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 30200
이제 nodeport service 를 생성하자
$ kubectl create -f nodeport-nginx.yaml
service/nodeport-service created
서비스를 확인하면 정의한 IP, PORT 로 생성 되었다.
[node1 ~]$kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
clusterip-service ClusterIP 10.100.100.100 <none> 80/TCP 20m
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 59m
nodeport-service NodePort 10.100.100.200 <none> 80:30200/TCP 51s
이제 노드 IP로 직접 호출 되는지 노드 포트로 호출하여 통신 되는지 확인한다.
[node1 ~]$ curl 192.168.0.22:30200
#1
[node1 ~]$ curl 192.168.0.22:30200
#2
[node1 ~]$ curl 192.168.0.22:30200
#1
[node1 ~]$ curl 192.168.0.22:30200
#2
그 다음 클러스터 IP 기능도 확인을 위해 clusterip 로 호출도 해본다.
[node1 ~]$ curl 10.100.100.200
#2
[node1 ~]$ curl 10.100.100.200
#3
[node1 ~]$ curl 10.100.100.200
#3
[node1 ~]$ curl 10.100.100.200
#3
[node1 ~]$ curl 10.100.100.200
#2
[node1 ~]$ curl 10.100.100.200
#2
다음 실습을 위해 모든 서비스를 삭제 한다.
$ kubectl delete svc --all
이제 LoadBalancer 타입에 대해 알아보자!
LoadBalancer 타입은 클라우드에서 운영 가능하며
External IP(외부에서 접속 가능한 IP, LB IP)를 할당하고 각 노드의 nodeport 외부 접근을 허용해주는것이다.
External IP를 할당 할때 LoadBalancer 를 클라우드에 구성 요청을 하나 현재 클라우드에 구성하지 않았으니 External IP 를 할당 받지는 못할것이다.
그러나 어떻게 동작하는지 보기 위해 만들어 보는 실습을 하도록 하자!
# loadbalancer-nginx.yaml
apiVersion: v1
kind: Service
metadata:
name: loadbalancer-nginx
spec:
type: LoadBalancer
selector:
app: webui
ports:
- protocol: TCP
port: 80
targetPort: 80
이제 서비스를 생성해본다!
$ kubectl create -f loadbalancer-nginx.yaml
service/loadbalancer-nginx created
서비스를 확인하면 External ip 가 pending 상태이다. 이는 로드 밸런서가 생성 되지 않았기 때문이다.
만약 클라우드에서 생성 한다면 외부에서 접속가능한 IP 가 할당 되어 외부에서 클러스터에 IP 로 호출시 파드와 통신 가능하게 된다.
[node1 ~]$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 8m21s
loadbalancer-nginx LoadBalancer 10.109.9.24 <pending> 80:30280/TCP 14s
노드포트와 동일하게 각 노드의 IP에 포트로 호출이 가능하다.
[node1 ~]$ curl 192.168.0.22:30280
#1
[node1 ~]$ curl 192.168.0.22:30280
#2
[node1 ~]$ curl 192.168.0.22:30280
#3
[node1 ~]$ curl 192.168.0.22:30280
#2
[node1 ~]$
이제 ExternalName에 대해 알아보자!
클러스터 내부에서 외부로 나갈수있는 도메인을 설정하는 서비스로 전체 파드에 dns 설정하는것이라고 생각하면 된다.
실습을 하면서 알아보자!
# external-service.yaml
apiVersion: v1
kind: Service
metadata:
name: external-svc
spec:
type: ExternalName
externalName: google.com
해당 서비스를 생성한다.
$ kubectl create -f external-service.yaml
service/external-svc created
서비스를 확인하면 external ip 가 생성 되었으며 서비스를 호출하면 external ip로 호출하게 된다.
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
external-svc ExternalName <none> google.com <none> 33s
이제 centos 파드를 생성하여 내부에서 서비스를 호출하면 google 로 호출한것을 알 수 있다.
$kubectl run my-centos -it --image=centos:7
If you don't see a command prompt, try pressing enter.
[root@my-centos /]# curl external-svc
<!DOCTYPE html>
<html lang=en>
<meta charset=utf-8>
<meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width">
<title>Error 404 (Not Found)!!1</title>
<style>
*{margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px}* > body{background:url(//www.google.com/images/errors/robot.png) 100% 5px no-repeat;padding-right:205px}p{margin:11px 0 22px;overflow:hidden}ins{color:#777;text-decoration:none}a img{border:0}@media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}}#logo{background:url(//www.google.com/images/branding/googlelogo/1x/googlelogo_color_150x54dp.png) no-repeat;margin-left:-5px}@media only screen and (min-resolution:192dpi){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat 0% 0%/100% 100%;-moz-border-image:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) 0}}@media only screen and (-webkit-min-device-pixel-ratio:2){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat;-webkit-background-size:100% 100%}}#logo{display:inline-block;height:54px;width:150px}
</style>
<a href=//www.google.com/><span id=logo aria-label=Google></span></a>
<p><b>404.</b> <ins>That’s an error.</ins>
<p>The requested URL <code>/</code> was not found on this server. <ins>That’s all we know.</ins>
끝!