본문 바로가기
kubenetes

kubernetes python flask ingress 설정하기

by kyeongseo.oh 2022. 3. 27.

목표 : clusterip로 올린 service를 ingress를 사용해 외부에서 접근 가능하도록 할 예정

 

FLASK DOCKER BUILD 여기에서 만든 FLASK IMAGE를 사용해 ip/flask를 입력하면 flask web ui가 나오게 INGRESS 설정을 하려고 했는 데 자꾸 아래와 같은 에러가 발생함.

 

404 not found error

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>404 Not Found</title>
<h1>Not Found</h1>
<p>The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.</p>

503 error

<html>
<head><title>503 Service Temporarily Unavailable</title></head>
<body>
<center><h1>503 Service Temporarily Unavailable</h1></center>
<hr><center>nginx</center>
</body>
</html>

 

 

해결방안을 정리해봄

 

 

일단 ingress를 사용하기 위해서는 ingress-controller를 구성해야한다. 필수임

vm(bare metal)에 k8s를 클러스터를 구축한 경우에는 baremetal ingress yaml 파일을 다운받아 사용하면 된다.

ingress-nginx 참고

1. nginx ingress controller 생성

[root@kw1 ~]# kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.1.2/deploy/static/provider/baremetal/deploy.yaml
namespace/ingress-nginx created
serviceaccount/ingress-nginx created
serviceaccount/ingress-nginx-admission created
role.rbac.authorization.k8s.io/ingress-nginx created
role.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrole.rbac.authorization.k8s.io/ingress-nginx created
clusterrole.rbac.authorization.k8s.io/ingress-nginx-admission created
rolebinding.rbac.authorization.k8s.io/ingress-nginx created
rolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
configmap/ingress-nginx-controller created
service/ingress-nginx-controller created
service/ingress-nginx-controller-admission created
deployment.apps/ingress-nginx-controller created
job.batch/ingress-nginx-admission-create created
job.batch/ingress-nginx-admission-patch created
ingressclass.networking.k8s.io/nginx created
validatingwebhookconfiguration.admissionregistration.k8s.io/ingress-nginx-admission created

 

ingress-nginx namespace에 pod이 생성된다. 다음과 같이 출력되면 정상임

[root@kw1 ~]# kubectl get pods --namespace=ingress-nginx
NAME                                        READY   STATUS      RESTARTS   AGE
ingress-nginx-admission-create-n9b9d        0/1     Completed   0          18m
ingress-nginx-admission-patch-5v4gd         0/1     Completed   1          18m
ingress-nginx-controller-5b6f946f99-6n9r5   1/1     Running     0          18m

 

아래와 같이 ingress-nginx-controller service가 nodePort로 올라와야함

[root@kw1 ~]# kubectl get svc -n ingress-nginx
NAME                                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx-controller             NodePort    10.111.2.246    <none>        80:32264/TCP,443:31477/TCP   2d1h
ingress-nginx-controller-admission   ClusterIP   10.106.74.229   <none>        443/TCP                      2d1h

 

2. flask docker image 빌드

FLASK DOCKER BUILD 이 코드를 조금 수정해서 이미지를 새로 빌드해서 사용할 예정

ksFlask.py의 내용을 아래와 같이 변경해줌

중요 "@app.route('/flask')이 route와 ingress의 path를 동일하게 설정해줘야한다."

from flask import Flask, render_template, url_for

app = Flask(__name__)


@app.route('/')
def image():
   return render_template("index.html")

if __name__ == "__main__":
   app.run(host="0.0.0.0")

 

이미지를 빌드한다. 태그를 별도 지정하지 않아 latest 태그가 붙었음 (맨 뒤에 . 하나 안 쓰면 에러남)

[root@kw1 flasktest]# docker build -t harbor.ks.io/privatetest/flasktest .
Successfully built 38b609e9c5bb
Successfully tagged harbor.ks.io/privatetest/flasktest:latest

 

 

3. pod, service, ingress 생성

하나하나 하기 귀찮으니까 한번에 다 생성하도록 한다.

kskube.yaml 파일을 하나 생성했다. pod, service, ingress 순으로 작성함

파일 하나에 pod을 여러 개 정의하거나, 아래와 같이 하나의 파일에 pod, service, ingress를 여러 개 정의할 때는

`---` 작대기 3개로 분리하면 된다. `---` 이걸 기준으로 파일 여러 개로 나눠서 각각 apply 해도 상관없음.

kind: Pod
apiVersion: v1
metadata:
  name: ksimage-app
  labels:
  ## 이 app이름이 service의 selector app과 동일해야함.
    app: ksimage
spec:
  containers:
    - name: ksimage-app
      image: harbor.ks.io/privatetest/flasktest:latest
      imagePullPolicy: IfNotPresent

---
kind: Service
apiVersion: v1
metadata:
## 이 부분이 ingress의 service - name과 동일해야함
  name: ksimage-service
spec:
  selector:
  ## 이 부분이 pod의 labels의 app과 동일해야함
    app: ksimage
  ports:
  ## 이 포트가 ingress port - number와 동일해야함
    - port: 5000

---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ksimage-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"
    ingress.kubernetes.io/rewrite-target: /

spec:
  rules:
  - http:
      paths:
      ## ip:port/flask로 접근하면 ksimage-service로 연결해준다는 의미
        - path: /flask
          pathType: Prefix
          backend:
            service:
              name: ksimage-service
              port:
              ## service의 port와 동일하게 설정
                number: 5000

 

이제 apply해준다. 한번에 pod, service, ingress를 동작시킬 수 있다.

[root@kw1 ~]# kubectl apply -f kskube.yaml
pod/ksimage-app created
service/ksimage-service created
ingress.networking.k8s.io/ksimage-ingress created

 

kubectl get all 커맨드로 pod, service, deploy 정보를 한번에 볼 수 있다.

확인해보니 모두 정상적으로 구동중으로 확인된다.

[root@kw1 ~]# kubectl get all
NAME              READY   STATUS    RESTARTS   AGE
pod/ks-app        1/1     Running   0          4h26m
pod/ksflask-app   1/1     Running   0          124m
pod/ksimage-app   1/1     Running   0          21s

NAME                      TYPE        CLUSTER-IP       EXTERNAL-IP                 PORT(S)    AGE
service/ks-service        ClusterIP   10.102.236.171   172.30.1.144,172.30.1.145   5678/TCP   4h25m
service/ksflask-service   ClusterIP   10.105.60.189    <none>                      5000/TCP   164m
service/ksimage-service   ClusterIP   10.99.222.55     <none>                      5000/TCP   21s
service/kubernetes        ClusterIP   10.96.0.1        <none>                      443/TCP    5h3m

 

ingress도 잘 올라왔는 지 확인해준다. ADDRESS가 빈 값일 수도 있는 데 조금만 기다리면 정상적으로 올라오니까 

조금 기다리면 된다.

[root@kw1 ~]# kubectl get ing
NAME              CLASS    HOSTS   ADDRESS        PORTS   AGE
example-ingress   <none>   *       172.30.1.145   80      5h58m
kf-ingress        <none>   *       172.30.1.145   80      6h1m
ks-ingress        <none>   *       172.30.1.145   80      16h
ksflask-ingress   <none>   *       172.30.1.145   80      165m
ksimage-ingress   <none>   *       172.30.1.145   80      80s

 

4. WEB 접속 테스트

잘 구동중이니 WEB에서 접속 테스트를 진행해본다.

접속하는 방법은 SERVERIP:INGRESSPORT/flask를 web 검색창에 입력하면 된다.

내가 테스트한 server의 hostname은 kw1.dd.io이고, INGRESSPORT는 아래에 보면 80:32264로 http로 접속할 경우 32264를 사용하면 된다.

최종적으로 접속 url은 kw1.dd.io:32264/flask

C:\Windows\System32\drivers\etc\hosts파일에 호스트 등록을 해놔서 hostname으로 접속 가능함

[root@kw1 ~]# kubectl get svc -n ingress-nginx
NAME                                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx-controller             NodePort    10.111.2.246    <none>        80:32264/TCP,443:31477/TCP   2d1h
ingress-nginx-controller-admission   ClusterIP   10.106.74.229   <none>        443/TCP                      2d1h

 

매우 이쁨

 


결론

적어놓긴 했지만 내가 못 찾을 예정이라 다시 정리하면

flask code의 @app.route('/flask') 이 부분과 ingress yaml의 path: /flask 이 부분을 동일하게 맞춰줘야 ingress 설정이 제대로 먹힌다.

@app.route('/')이고 path: /flask 이면 ingress 404나 503 error가 난다. 그러니 자알 맞춰주도록 하자.

댓글