[Kubernetes] Ingress

pingping·2021년 2월 14일
1

Kubernetes

목록 보기
7/10
post-thumbnail
post-custom-banner

Ingress란?

  • Ingress는 L7 Load Balancer이며 Cluster 외부에서 안으로 접근하는 요청들을 어떻게 처리할지 정의해둔 규칙 모음이다.

  • URL을 사용할 수 있도록 해주고 Traffic Load Balancing, SSL 인증서 처리, 도메인 기반 가상 호스팅 또한 제공한다.

  • Ingress Controller를 Kubernetes 내부 혹은 외부 어디에 두느냐에 따라 Packet 흐름이 달라진다.

    ⇒ On-Premises : 클러스터 내부에 Pod로 구현된다.

    ⇒ Public Cloud : 클러스터 외부에 존재한다.

출처 : 오리뎅이 Slideshare

Nginx-Ingress Controller 설치 및 테스트

# kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.44.0/deploy/static/provider/baremetal/deploy.yaml

# kubectl get pods -n ingress-nginx
NAME                                        READY   STATUS      RESTARTS   AGE
ingress-nginx-admission-create-5gqc5        0/1     Completed   0          12m
ingress-nginx-admission-patch-j8rzn         0/1     Completed   1          12m
ingress-nginx-controller-67897c9494-z7ljs   1/1     Running     0          12m

# kubectl get all -n ingress-nginx
NAME                                            READY   STATUS      RESTARTS   AGE
pod/ingress-nginx-admission-create-5gqc5        0/1     Completed   0          12m
pod/ingress-nginx-admission-patch-j8rzn         0/1     Completed   1          12m
pod/ingress-nginx-controller-67897c9494-z7ljs   1/1     Running     0          12m

NAME                                         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
service/ingress-nginx-controller             NodePort    10.233.32.198   <none>        80:30888/TCP,443:31204/TCP   12m
service/ingress-nginx-controller-admission   ClusterIP   10.233.30.1     <none>        443/TCP                      12m

NAME                                       READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/ingress-nginx-controller   1/1     1            1           12m

NAME                                                  DESIRED   CURRENT   READY   AGE
replicaset.apps/ingress-nginx-controller-67897c9494   1         1         1       12m

NAME                                       COMPLETIONS   DURATION   AGE
job.batch/ingress-nginx-admission-create   1/1           6s         12m
job.batch/ingress-nginx-admission-patch    1/1           6s         12m
  • Test를 위한 Nginx Deployment, Service 생성
root@instance-1:~# kubectl create deployment nginx nginx --image=nginx

root@instance-1:~# kubectl expose deployment nginx --type=NodePort --port=80 --target-port=80
service/nginx exposed

root@instance-1:~# kubectl get svc
NAME                TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
clusterip-service   ClusterIP      10.233.23.13    <none>        80/TCP         14h
ext-service         ExternalName   <none>          google.com    <none>         11h
headless-svc        ClusterIP      None            <none>        80/TCP         11h
kubernetes          ClusterIP      10.233.0.1      <none>        443/TCP        6d17h
my-service          NodePort       10.233.53.193   <none>        80:30007/TCP   12h
nginx               NodePort       10.233.7.196    <none>        80:30456/TCP   7s

# nginx 서비스의 cluster-ip로 curl 명령어 날림
root@instance-1:~# curl 10.233.7.196
<!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>
  • Ingress Template

    Path만 설정해주었다.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: minimal-ingress
	# 인그레스를 설정할 때 .metadata.annotations 하위 필드를 사용해야 한다.
	# 각 인그레스 컨트롤러마다 설정이 다르다.
	# / 경로로 리다이렉트하라는 뜻이다.
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
	# 규칙들을 지정해줄 수 있다.
  rules:
	# foo.bar.com의 주소로 요청이 들어올 시 다음에 설정하는 규칙에 따라 처리
  - host: "foo.bar.com"
    http:
      paths:
      - path: /login
        pathType: Prefix
        backend:
					# nginx라는 서비스의 80번 포트로 보낸다.
          service:
            name: nginx
            port:
              number: 80
  - host: "foo.bar.com"
    http:
      paths:
      - path: /logout
        pathType: Prefix
        backend:
					# nginx라는 서비스의 80번 포트로 보낸다.
          service:
            name: nginx
            port:
              number: 80
  • Ingress 생성

    Web에서 접속할 때는 ingress-nginx-controller svc의 nodeport로 접속하여야 한다.

root@instance-1:~/kubernetes-sample/ing# kubectl get svc -n ingress-nginx
NAME                                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
**ingress-nginx-controller             NodePort    10.233.32.198   <none>        80:30888/TCP,443:31204/TCP   28m**
ingress-nginx-controller-admission   ClusterIP   10.233.30.1     <none>        443/TCP                      28m

root@instance-1:~/kubernetes-sample/ing# kubectl describe ing
Name:             minimal-ingress
Namespace:        default
Address:          10.142.0.5
Default backend:  default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
**Rules:
  Host         Path  Backends
  ----         ----  --------
  foo.bar.com  
               /login   nginx:80 (10.233.125.37:80)
  foo.bar.com  
               /logout   nginx:80 (10.233.125.37:80)**
Annotations:   nginx.ingress.kubernetes.io/rewrite-target: /
Events:
  Type    Reason  Age                  From                      Message
  ----    ------  ----                 ----                      -------
  Normal  Sync    40s (x3 over 2m56s)  nginx-ingress-controller  Scheduled for sync

Window에서의 hosts 파일은 C:\Windows\System32\drivers\etc\hosts 에 있다.

해당 파일을 메모장이나 편집기 등으로 열어서 수정해주자.

<<instance-1 or 5의 external ip>> foo.bar.com


  • PATH를 login, logout 2개의 경로로 나누어서 접속할 수 있도록 설정하였다.
  • 인그레스 컨트롤러 자체도 kubernetes cluster 위에서 동작하므로 인그레스 컨트롤러에 접근하기 위해 NodePort 타입의 서비스를 만들어주어 접근하였다.

Ingress SSL 적용

  • Test용이므로 OpenSSL 프로그램을 이용하여 직접 인증서를 만들어 테스트한다.
root@instance-1:~/kubernetes-sample/ing# openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=foo.bar.com"
Generating a 2048 bit RSA private key
........................................................................................................................................................................................................................................................................+++
..+++
writing new private key to 'tls.key'
-----

# 키, 인증서 확인
root@instance-1:~/kubernetes-sample/ing# ls
ingress.yaml  tls.crt  tls.key

# 시크릿 생성
root@instance-1:~/kubernetes-sample/ing# kubectl create secret tls foo-secret --key tls.key --cert tls.crt 
secret/foo-secret created

# secret 확인
root@instance-1:~/kubernetes-sample/ing# kubectl describe secrets foo-secret 
Name:         foo-secret
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  kubernetes.io/tls

Data
====
tls.crt:  1099 bytes
tls.key:  1704 bytes
  • Secret을 Ingress에 적용

    443 포트가 31204 NodePort와 바인딩이 된 것을 확인할 수 있다.

# 수정사항 적용
root@instance-1:~/kubernetes-sample/ing# kubectl apply -f ingress.yaml 
ingress.networking.k8s.io/minimal-ingress configured

# 포트 확인
root@instance-1:~/kubernetes-sample/ing# kubectl get svc -n ingress-nginx 
NAME                                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
**ingress-nginx-controller             NodePort    10.233.32.198   <none>        80:30888/TCP,443:31204/TCP   84m**
ingress-nginx-controller-admission   ClusterIP   10.233.30.1     <none>        443/TCP                      84m
  • 사설 인증서이기 때문에 Not Secure 메시지를 확인할 수 있다.

무중단 배포 시 주의할 점

Rolling Update

  • 쿠버네티스에서는 무중단 배포를 지원하는데 대표적인 3가지 방법이 있다. Blue/Green, Rolling Update, Canary
  • 그 중 가장 많이 사용되는 배포 방식 중 하나인 Rolling Update에 대해서 알아보겠다. Rolling Update는 새 버전을 배포하면서 새 버전 인스턴스를 하나씩 늘려가고 구 버전 인스턴스를 하나씩 줄여나가는 방법이다.

maxSurge, maxUnavailable

  • maxSurge : 업데이트 중 여분의 파드를 몇 개 더 추가할 수 있는지
  • maxUnavailable : 업데이트 중 몇 개의 파드를 이용할 수 없어도 되는지 설정

⇒ 두 필드 값을 한꺼번에 0으로 설정할 수는 없다. Pod가 없을 수 있기 때문이다.

pod가 readinessProbe를 지원하는지 확인

  • readinessProbe는 컨테이너가 서비스 요청을 처리할 준비가 되었는지 진단한다.

    예를 들어 Java Process를 실행했을 때 초기화 과정이 긴데 이 때 livenessProbe가 OK더라도 readinessProbe를 따로 지원하지 않으면 아직 준비되지 않은 컨테이너에 요청이 가서 응답이 제대로 오지 않을 수 있으므로 readinessProbe를 설정해주어야 한다.

  • readinessProbe를 설정하기 힘들다면 .spec.minReadySeconds 필드를 이용해 어느 정도 비슷한 효과를 낼 수 있다. 이 필드는 Pod가 준비 상태일 때까지의 최소 대기 시간으로 기본값은 0이다.

그레이스풀 종료 설정

  • Node 내에서 컨테이너들을 관리하는 Kubelet은 새 파드가 실행되고 이전 파드를 종료할 때 SIGTERM 신호를 먼저 보낸다. 무중단 배포를 하려면 컨테이너에서 SIGTERM 신호를 받았을 때 기존에 받은 요청만 처리를 완료하고 새 요청을 받지 않는 그레이스풀 종료가 설정되어 있어야 한다.
  • 대기 시간은 .terminationGracePeriodSeconds 필드로 설정할 수 있으며 default는 30초이다.


  • 아래 사이트들을 참고하며 정리하였습니다.

https://kubernetes.io/ko/docs/concepts/services-networking/ingress/

https://kubernetes.github.io/ingress-nginx/deploy/#installation-guide

https://www.slideshare.net/InfraEngineer/ss-186475759

profile
Cloud Infra Engineer & interested in python, IaC, k8s
post-custom-banner

0개의 댓글