지금까지 구축된 kubernetes에서 ingress-nginx를 설치하고 "Deployment, Service, HorizontalPodAutoscaler"로 구성된 앱을 배포하고
ingress를 구성 후, 최종 서비스 형태를 만드는것을 목표로 한다.

ingress-nginx를 구축하여 서비스하는 구성도

서비스용 앱 배포

모든 요청에 응답하는 echo server를 앱으로 아래와 같은 파일로 구성해서 배포한다.

echo-server-dpm.yaml - Deployment

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: echo-server-dpm
  labels:
    app: echo-server
spec:
  replicas: 1
  selector:
    matchLabels:
      app: echo-server
  template:
    metadata:
      labels:
        app: echo-server
    spec:
      containers:
      - name: echo-server-pod
        image: ealen/echo-server
        resources:
          requests:
            cpu: 100m
            memory: 200Mi
        ports:
        - name: http
          containerPort: 80
# kubectl apply -f echo-server-dpm.yaml

 

echo-server-svc.yaml - Service

---
apiVersion: v1
kind: Service
metadata:
  name: echo-server-svc
  labels:
    app: echo-server
spec:
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: echo-server
# kubectl apply -f echo-server-svc.yaml

 

echo-server-hpa.yaml - HorizontalPodAutoscaler

---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: echo-server-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: echo-server-dpm
  minReplicas: 2
  maxReplicas: 100
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 30
# kubectl apply -f echo-server-hpa.yaml

 

구성 검증

1. HorizontalPodAutoscaler

# kubectl get hpa
NAME              REFERENCE                    TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
echo-server-hpa   Deployment/echo-server-dpm   0%/30%    2         100       2          15m

위와 같이 배포된 hpa에서 메트릭이 올바로 수집되고 있는지 확인한다.

2. Service

# kubectl get svc
NAME              TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
echo-server-svc   ClusterIP   10.233.28.255   <none>        80/TCP    16m

위와 같이 svc가 구성되어 있는지 확인한다.

3. 서비스 확인 (echo server pod에 연결해서 localhost/hello, echo-server-svc/hello로 호출해본다.

root@homemachine:~/echo-server-deployment# kubectl get pod
NAME                               READY   STATUS    RESTARTS   AGE
echo-server-dpm-5f6899f47d-9l954   1/1     Running   0          20m
echo-server-dpm-5f6899f47d-tz64q   1/1     Running   0          17m
metrics-server-55cc5bcdb8-qfkhv    1/1     Running   0          21h


root@homemachine:~/echo-server-deployment# kubectl exec -ti echo-server-dpm-5f6899f47d-9l954 -- /bin/sh
/app # wget -O - localhost/hello
Connecting to localhost ([::1]:80)
writing to stdout
{"host":{"hostname":"localhost","ip":"::1","ips":[]},"http":{"method":"GET","baseUrl":"","originalUrl":"/hello","protocol":"http"},"request":{"params":{"0":"/hello"},"query":{},"cookies":{},"body":{},"headers":{"host":"localhost","user-agent":"Wget","connection":"close"}},"environment":{"PATH":"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","HOSTNAME":"echo-server-dpm-5f6899f47d-9l954","NODE_VERSION":"20.11.0","YARN_VERSION":"1.22.19","METRICS_SERVER_SERVICE_HOST":"10.233.20.91","METRICS_SERVER_PORT":"tcp://10.233.20.91:443","KUBERNETES_SERVICE_HOST":"10.233.0.1","KUBERNETES_SERVICE_PORT":"443","KUBERNETES_SERVICE_PORT_HTTPS":"443","KUBERNETES_PORT_443_TCP_PORT":"443","KUBERNETES_PORT_443_TCP_ADDR":"10.233.0.1","METRICS_SERVER_PORT_443_TCP":"tcp://10.233.20.91:443","METRICS_SERVER_PORT_443_TCP_PORT":"443","KUBERNETES_PORT_443_TCP_PROTO":"tcp","METRICS_SERVER_SERVICE_PORT_HTTPS":"443","METRICS_SERVER_PORT_443_TCP_ADDR":"10.233.20.91","KUBERNETES_PORT":"tcp://10.233.0.1:443","KUBERNETES_PORT_443_TCP":"tcp://10.233.0.1:443","METRICS_SERVER_SERVICE_PORT":"443","METRICS_SERVER_PORT_443_TCP_PROTO":"-                    100% |*****************************************************************************|  1146  0:00:00 ETA
written to stdout

/app # wget -O - echo-server-svc/hello
Connecting to echo-server-svc (10.233.28.255:80)
writing to stdout
{"host":{"hostname":"echo-server-svc","ip":"::ffff:10.233.74.70","ips":[]},"http":{"method":"GET","baseUrl":"","originalUrl":"/hello","protocol":"http"},"request":{"params":{"0":"/hello"},"query":{},"cookies":{},"body":{},"headers":{"host":"echo-server-svc","user-agent":"Wget","connection":"close"}},"environment":{"PATH":"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","HOSTNAME":"echo-server-dpm-5f6899f47d-tz64q","NODE_VERSION":"20.11.0","YARN_VERSION":"1.22.19","ECHO_SERVER_SVC_PORT":"tcp://10.233.28.255:80","ECHO_SERVER_SVC_PORT_80_TCP_PROTO":"tcp","METRICS_SERVER_SERVICE_HOST":"10.233.20.91","METRICS_SERVER_PORT_443_TCP_PORT":"443","METRICS_SERVER_PORT_443_TCP_ADDR":"10.233.20.91","KUBERNETES_SERVICE_HOST":"10.233.0.1","ECHO_SERVER_SVC_SERVICE_PORT_HTTP":"80","METRICS_SERVER_SERVICE_PORT":"443","METRICS_SERVER_SERVICE_PORT_HTTPS":"443","KUBERNETES_PORT":"tcp://10.233.0.1:443","ECHO_SERVER_SVC_PORT_80_TCP_PORT":"80","ECHO_SERVER_SVC_PORT_80_TCP_ADDR":"10.233.28.255","ECHO_SERVER_SVC_SERVICE_PORT":"80","KUBERNETES_SERVICE_PORT_HTTPS":"443","KUBERNETES_PORT_443_TCP":"tcp://10.233.0.1:443","KUBERNETES_PORT_443_TCP_PROTO":"tcp","KUBERNETES_PORT_443_TCP_ADDR":"10.233.0.1","ECHO_SERVER_SVC_SERVICE_HOST":"10.233.28.255","ECHO_SERVER_SVC_PORT_80_TCP":"tcp://10.233.28.255:80","METRICS_SERVER_PORT":"tcp://10.233.20.91:443","METRICS_SERVER_PORT_443_TCP":"tcp://10.233.20.91:443","METRICS_SERVER_PORT_443_TCP_PROTO":"tcp","KUBERNETES_SERVICE_PORT":"443","KUBERNETES_PORT_44-                    100% |*****************************************************************************|  1534  0:00:00 ETA
written to stdout

위와 같이 정상적인 호출이 온다면 앱은 정상적으로 배포되었다.

 

ingress-nginx 설치

아래와 같이 helm으로 template(ingress-nginx-deploy.yaml)을 생성한다.

차후 prometheus-operator를 구성해서 ingress-nginx의 metric 수집을 위한 옵션을 추가했고, ingress-nginx의 autoscale을 위해 옵션을 추가했다.

helm template ingress-nginx ingress-nginx \
--repo https://kubernetes.github.io/ingress-nginx \
--dependency-update --include-crds \
--set controller.metrics.enabled=true \
--set-string controller.podAnnotations."prometheus\.io/scrape"="true" \
--set-string controller.podAnnotations."prometheus\.io/port"="10254" \
--set controller.autoscaling.enabled=true \
--set controller.autoscaling.minReplicas=1 \
--set controller.autoscaling.maxReplicas=100 \
--set controller.autoscaling.targetCPUUtilizationPercentage=30 > ingress-nginx-deploy.yaml
# kubectl apply -f ingress-nginx-deploy.yaml --server-side

추가로 "--server-side" 옵션으로 배포를 추천한다.

https://kubernetes.github.io/ingress-nginx/deploy/
https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/monitoring.md

 

구성된 service를 확인해보면 아래와 같이 "192.168.122.11" IP로 Loadbalancer가 구성되어 있는 것을 확인할 수 있다. (상황에 따라 다른 IP가 할당될 수 있다.)

# kubectl get svc|grep ingress
ingress-nginx-controller                   LoadBalancer   10.233.39.240   192.168.122.11   80:31917/TCP,443:30506/TCP    79s
ingress-nginx-controller-admission         ClusterIP      10.233.52.85    <none>           443/TCP                       79s
ingress-nginx-controller-metrics           ClusterIP      10.233.23.2     <none>           10254/TCP                     79s

 

"192.168.122.11" IP로 호출해보면 ingress가 등록되지 않아 404 에러가 리턴된다.

# curl 192.168.122.11
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx</center>
</body>
</html>

 

서비스용 앱 Ingress 배포

echo-server-ing.yaml - Ingress

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: echo-server-ing
spec:
  ingressClassName: nginx
  rules:
  - host:
    http:
      paths:
      - pathType: Prefix
        path: /hello
        backend:
          service:
            name: echo-server-svc
            port:
              number: 80
# kubectl apply -f echo-server-ing.yaml

 

Loadbalancer(192.168.122.11)로 호출 테스트를 진행해보면 아래와 같이 결과가 나와야 정상적으로 구축된 것이다.

# curl 192.168.122.11/hello
{"host":{"hostname":"192.168.122.11","ip":"::ffff:10.233.71.7","ips":[]},"http":{"method":"GET","baseUrl":"","originalUrl":"/hello","protocol":"http"},"request":{"params":{"0":"/hello"},"query":{},"cookies":{},"body":{},"headers":{"host":"192.168.122.11","x-request-id":"771b6bf061a0b118e8d912fcdeddfda6","x-real-ip":"10.233.120.0","x-forwarded-for":"10.233.120.0","x-forwarded-host":"192.168.122.11","x-forwarded-port":"80","x-forwarded-proto":"http","x-forwarded-scheme":"http","x-scheme":"http","user-agent":"curl/7.81.0","accept":"*/*"}},"environment":{"PATH":"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","HOSTNAME":"echo-server-dpm-5f6899f47d-tz64q","NODE_VERSION":"20.11.0","YARN_VERSION":"1.22.19","ECHO_SERVER_SVC_PORT":"tcp://10.233.28.255:80","ECHO_SERVER_SVC_PORT_80_TCP_PROTO":"tcp","METRICS_SERVER_SERVICE_HOST":"10.233.20.91","METRICS_SERVER_PORT_443_TCP_PORT":"443","METRICS_SERVER_PORT_443_TCP_ADDR":"10.233.20.91","KUBERNETES_SERVICE_HOST":"10.233.0.1","ECHO_SERVER_SVC_SERVICE_PORT_HTTP":"80","METRICS_SERVER_SERVICE_PORT":"443","METRICS_SERVER_SERVICE_PORT_HTTPS":"443","KUBERNETES_PORT":"tcp://10.233.0.1:443","ECHO_SERVER_SVC_PORT_80_TCP_PORT":"80","ECHO_SERVER_SVC_PORT_80_TCP_ADDR":"10.233.28.255","ECHO_SERVER_SVC_SERVICE_PORT":"80","KUBERNETES_SERVICE_PORT_HTTPS":"443","KUBERNETES_PORT_443_TCP":"tcp://10.233.0.1:443","KUBERNETES_PORT_443_TCP_PROTO":"tcp","KUBERNETES_PORT_443_TCP_ADDR":"10.233.0.1","ECHO_SERVER_SVC_SERVICE_HOST":"10.233.28.255","ECHO_SERVER_SVC_PORT_80_TCP":"tcp://10.233.28.255:80","METRICS_SERVER_PORT":"tcp://10.233.20.91:443","METRICS_SERVER_PORT_443_TCP":"tcp://10.233.20.91:443","METRICS_SERVER_PORT_443_TCP_PROTO":"tcp","KUBERNETES_SERVICE_PORT":"443","KUBERNETES_PORT_443_TCP_PORT":"443","HOME":"/root"}}