[클라우드/K8S 기본(3) - Service, 노드포트와 인그레스]

SooYeon Yeon·2022년 9월 13일
0

클라우드 K8S

목록 보기
5/18
post-thumbnail

Service를 이용해 외부 접속 가능하게 하기

targetPort는 Pod포트

service.yaml

apiVersion: v1
kind: Service
metadata:
  name: my-nginx-lb
spec:
  type: LoadBalancer
  ports:
    - port: 80 # 로드밸런서의 포트
      targetPort: 80 # 포드의 포트
      protocol: TCP
  selector:
    app: my-nginx-pods-label # 해당 라벨에 붙어있는 곳에만 보냄
  • nginx deploy와 LB 서비스 배포
dustndus8@cloudshell:~/0901 (rapa-0901-ysy)$ kubectl apply -f nginx-deploy.yaml
deployment.apps/deploy-nginx created
dustndus8@cloudshell:~/0901 (rapa-0901-ysy)$ kubectl apply -f service.yaml
service/my-nginx-lb created
dustndus8@cloudshell:~/0901 (rapa-0901-ysy)$ kubectl get pod
NAME                            READY   STATUS    RESTARTS   AGE
deploy-nginx-7f797dbc66-8x5kv   1/1     Running   0          7s
deploy-nginx-7f797dbc66-rbflg   1/1     Running   0          7s
deploy-nginx-7f797dbc66-tsn6m   1/1     Running   0          7s
  • srv봐서 IP로 접속(LB의 External IP)
dustndus8@cloudshell:~/0901 (rapa-0901-ysy)$ kubectl get svc
NAME          TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)        AGE
kubernetes    ClusterIP      10.100.0.1      <none>          443/TCP        5h48m
my-nginx-lb   LoadBalancer   10.100.11.139   34.97.196.150   80:30252/TCP   3m29s

  • httpd로 이미지 업데이트
dustndus8@cloudshell:~/0901 (rapa-0901-ysy)$ kubectl set image deploy deploy-nginx nginx=httpd:latest
deployment.apps/deploy-nginx image updated

  • 다시 nginx로 undo
dustndus8@cloudshell:~/0901 (rapa-0901-ysy)$ kubectl rollout undo deploy deploy-nginx --to-revision=1
deployment.apps/deploy-nginx rolled back

실습 후 삭제

kubectl delete deploy,pod,svc —all

서비스

노드포트

selector → label 지정

  1. replicaset : 어떤 포드의 라벨을 확인하고 지정된 개수를 유지할 것인가에 홀용 → label 이용
  2. service : (노드 포트에서) 노드의 포트로 접속된 트래픽에 대해 누구(pod)에게 전달할 것인가 → label 이용

port 80: nodePort로 접속된 트래픽을 nodeport 서비스의 특정 포트(80/tcp)로 유입되면 (2)

targetPort 80: 최종적으로 목적지 pod의 80번 포트로 전달하겠다 (3)

nodePort : 외부에서 가상머신의 어떤 포트로 접속하면? (1)

  • yaml 파일
apiVersion: v1
kind: Service
metadata:
  name: test
spec:
  selector:
    color: blue
  ports:
  - name: http
    protocol: TCP
    port: 80
    targetPort: 80
    nodePort: 30000
  type: NodePort
  • 배포
dustndus8@cloudshell:~/0902 (rapa-0901-ysy)$ kubectl apply -f nginx1.yaml
service/test created
dustndus8@cloudshell:~/0902 (rapa-0901-ysy)$ kubectl get svc
NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP   10.100.0.1     <none>        443/TCP        18h
test         NodePort    10.100.7.230   <none>        80:30000/TCP   11s

IP 확인

dustndus8@cloudshell:~/0902 (rapa-0901-ysy)$ kubectl get node -o wide
NAME                                           STATUS   ROLES    AGE   VERSION            INTERNAL-IP   EXTERNAL-IP    OS-IMAGE             KERNEL-VERSION   CONTAINER-RUNTIME
gke-mytestcluster-default-pool-b3369d01-gtnl   Ready    <none>   24h   v1.22.11-gke.400   10.174.0.4    34.97.47.61    Ubuntu 20.04.4 LTS   5.4.0-1076-gke   docker://19.3.8
gke-mytestcluster-default-pool-b3369d01-n9rz   Ready    <none>   24h   v1.22.11-gke.400   10.174.0.2    34.97.1.232    Ubuntu 20.04.4 LTS   5.4.0-1076-gke   docker://19.3.8
gke-mytestcluster-default-pool-b3369d01-qkz5   Ready    <none>   24h   v1.22.11-gke.400   10.174.0.3    34.97.92.199   Ubuntu 20.04.4 LTS   5.4.0-1076-gke   docker://19.3.8

30000포트 접속하기 위해 방화벽설정

dustndus8@cloudshell:~/0902 (rapa-0901-ysy)$ gcloud compute firewall-rules create permitnp --allow=tcp:30000
Creating firewall...working..Created [https://www.googleapis.com/compute/v1/projects/rapa-0901-ysy/global/firewalls/permitnp].
Creating firewall...done.
NAME: permitnp
NETWORK: default
DIRECTION: INGRESS
PRIORITY: 1000
ALLOW: tcp:30000
DENY:
DISABLED: False

지우고싶다면 delete로

  • scale 조정
dustndus8@cloudshell:~ (rapa-0901-ysy)$ kubectl scale --replicas 1 deploy test
deployment.apps/test scaled

External Traffic Policy: Cluster(기본값) : 해당 노드에 pod가 없다고 하더라도 클러스터를 통해 다른 노드에 있는 pod로 트래픽이 전송된다. 이때 hop을 바꾸기 때문에 결국 라우팅이 발생한다.

이를 Local로 변경하면 해당 노드에 있는 pod로만 접속하게 되고, 만약 pod가 없다면 서비스를 받을 수 없게 된다. 하지만 불필요한 라우팅은 없기 때문에 DC에 부담을 줄일 수 있게 된다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: test
spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 2
      maxUnavailable: 2
  replicas: 3
  selector:
    matchLabels:
      color: blue
  template:
    metadata:
      labels:
        color: blue
    spec:
      containers:
      - name: test
        image: nginx

---
apiVersion: v1
kind: Service
metadata:
  name: test
spec:
  selector:
    color: blue
  externalTrafficPolicy: Local
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 80
      nodePort: 30000
  type: NodePort

Local로 변경

배포 후 확인

dustndus8@cloudshell:~/0902 (rapa-0901-ysy)$ kubectl get pod,svc
NAME                        READY   STATUS    RESTARTS   AGE
pod/test-69454c947b-8q97s   1/1     Running   0          7s
pod/test-69454c947b-b997q   1/1     Running   0          7s
pod/test-69454c947b-zx77f   1/1     Running   0          150m

NAME                 TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
service/kubernetes   ClusterIP   10.100.0.1     <none>        443/TCP        20h
service/test         NodePort    10.100.7.230   <none>        80:30000/TCP   94m
dustndus8@cloudshell:~/0902 (rapa-0901-ysy)$ kubectl describe svc test
Name:                     test
Namespace:                default
Labels:                   <none>
Annotations:              cloud.google.com/neg: {"ingress":true}
Selector:                 color=blue
Type:                     NodePort
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.100.7.230
IPs:                      10.100.7.230
Port:                     http  80/TCP
TargetPort:               80/TCP
NodePort:                 http  30000/TCP
Endpoints:                10.96.0.23:80,10.96.1.25:80,10.96.2.25:80
Session Affinity:         None
External Traffic Policy:  Local
Events:                   <none>

replica 1로 scale 조정

dustndus8@cloudshell:~/0902 (rapa-0901-ysy)$ kubectl scale --replicas 1 deploy test
deployment.apps/test scaled
dustndus8@cloudshell:~/0902 (rapa-0901-ysy)$ kubectl get pod
NAME                    READY   STATUS    RESTARTS   AGE
test-69454c947b-zx77f   1/1     Running   0          152m

이후 세 페이지로 접속해보면 한 곳에서만 정상적으로 페이지가 보이고 나머지 2곳은 페이지로 접속되지 않는다.

인그레스(ingress)

ingress는 svc와 연결해서 사용해야 한다.

rules:
- host: www.test.com        1) www.test.com 2) www.test.com/ip , 3) www.test.com/y...
  http:
    paths
    - path
      backend:
        servicename: hname-svc-default -> 서비스를 제공하는 포트의 어떤 경로로 접속되도록 할 것인가? : / -> 포드의 기본 웹 디렉토리로 전달하겠다!!!

    포드에서는 아래와 같이 구성해야 한다.
      /var/www/html/index.html 

    - path: /ip
...
    - path: /your-directory
sudo vi /etc/hosts
34.97.1.23:2    www.test.pri

해당 내용 추가 IP는 3개의 노드 중 아무거나 등록

  • ingress 정의
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example # ingress이름
spec:
  rules:
  - host: www.test.pri
    http:
      paths:
        - path: /
          pathType: Prefix
          backend:
            service:
              name: example # 서비스 이름
              port:
                number: 80
  • ingress 컨트롤러 배포
kubectl apply -f \
https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.1.2/deploy/static/provider/cloud/deploy.yaml
  • 컨트롤러 동작 확인
dustndus8@cloudshell:~ (rapa-0901-ysy)$ kubectl get pods -A | grep nginx-controller
ingress-nginx   ingress-nginx-controller-cb87575f5-9vzz5                  1/1     Running     0          91s
  • 서비스 제공을 위한 pod 배포
dustndus8@cloudshell:~ (rapa-0901-ysy)$ kubectl run example --image=nginx
pod/example created

pod example을 외부에 노출. 포트는 80번을 통해 접속 가능하게 하고, 서비스 이름은 example, 서비스 타입은 NodePort를 이용해 배포

dustndus8@cloudshell:~ (rapa-0901-ysy)$ kubectl expose pod example --port=80 --name example --type=NodePort
service/example exposed
  • 포트 확인
dustndus8@cloudshell:~ (rapa-0901-ysy)$ kubectl get svc
NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
example      NodePort    10.100.15.20   <none>        80:30182/TCP   15s
kubernetes   ClusterIP   10.100.0.1     <none>        443/TCP        21h
test         NodePort    10.100.7.230   <none>        80:30000/TCP   163m

www.test.pri:30182 → nodeport:80 → pod/example:80

                                                           /var/www/html  → 우리는 여기 기본 디렉토리 접속되도록

                                                          /var/www/html/blog
  • ingress.yaml 파일에 anotation 추가

$1 이라고 하면 /blog, /shop을 구분하겠다는 뜻. 뒤 경로 똑같이 가게 하려면 $2

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example # ingress이름
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$1
    kubernetes.io/ingress.class: "nginx"

spec:
  rules:
  - host: www.test.pri
    http:
      paths:
        - path: /
          pathType: Prefix
          backend:
            service:
              name: example # 서비스 이름
              port:
                number: 80
  • 배포하기
dustndus8@cloudshell:~ (rapa-0901-ysy)$ kubectl apply -f ingress.yaml
ingress.networking.k8s.io/example created
  • 포트 열기위한 방화벽 설정
gcloud compute firewall-rules create permitingress --allow=tcp:30182
  • 최종 접속
curl -L http://www.test.pri:30182

kubernetes에서 로드밸런서는 public과 openstack과 같은 클라우드 환경에서 사용 가능하다. 만약 on-premise에서 LB를 사용하고싶다면 k8s와 연계 가능한 별도의 object가 필요하다.

이를 metallb를 통해 제공할 수 있다.

0개의 댓글