개발강의정리/DevOps

[데브옵스를 위한 쿠버네티스 마스터] 프라이빗 클라우드를 위한 인그레스 Ingress-Nginx 구현하기

nineDeveloper 2021. 1. 22.
728x90

로컬 쿠버네티스에 ingress-nginx 사용방법


1. ingress-nginx 개요

인그레스를 사용하면 L7의 웹 요청을 해석해서 단일 IP, 단일 포트로 다수의 도메인과 서비스로 연결할 수 있음
이 방법을 사용하면 웹페이지의 도메인은 같지만 다른 앱을 사용하는 것도 가능하게 한다
하지만 쿠버네티스에서 기본적으로 지원하는 인그레스 오브젝트는 클라우드 환경이 아니면 사용할 수 없다
클라우드에서 인그레스를 생성하면 외부에 게이트웨이를 생성하고 각 기능에 맞게 서비스에 연결한다
GCP의 경우에는 외부 게이트웨이에 L7 규칙이 적용돼 있다
이 포스트에 있는 nginx-ingress를 사용해보기 전에 GCP에서 제공하는 ingress를 한번 써보시길 권장한다

HTTP(S) 부하 분산용 GKE 인그레스

여기서는 로컬에서 인그레스를 사용할 수 있는 ingress-nginx를 설치하고 쿠버네티스에 포드 형태로 띄워서 설정하는 방법을 알아본다
nginx-ingress를 포드로 떠있으면서 다시 서비스로 연결할 수 있는 역할을 수행한다

Enterprise-grade application delivery for Kubernetes

그림출처: https://www.nginx.com/products/nginx/kubernetes-ingress-controller/

깃헙 사이트에서 nginx-ingress에 대한 예제를 몇개 제공하고 있다
그 중 가장 기본적인 예제를 분석하고 사용하도록 한다

https://github.com/kubernetes/ingress-nginx/blob/master/deploy/static/provider/baremetal/deploy.yaml


2. ingress-nginx 예제 분석

예제가 매우 길지만 이런 예제를 분석할 줄 알아야 우리의 환경에서 ingress-nginx가 정확히 어떻게 동작할지 예상할 수 있다
라인 수는 거의 300라인 정도 된다
하나씩 살펴보고 어떤 기능을 가질지 예상해 보자

[namespace]ingress-nginx

첫 번째 오브젝트부터 살펴보자
가장 먼저 네임스페이스를 선언한다
ingress-nginx라는 별도의 네임스페이스를 생성한다
앞으로 선언돼는 모든 오브젝트들은 이 네임스페이스에 할당된다
limitRange 는 yaml의 가장 아랫부분에 있는 오브젝트인데 네임스페이스의 자원할당량을 제한하는 역할을 수행하므로 네임스페이스와 함께 보자
여기서 생성되는 limitRange 는 컨테이너 최소 권장사항만 cpu 100m, 메모리 사용량 90Mi로 정의한다

apiVersion: v1
kind: Namespace
metadata:
  name: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
---

apiVersion: v1
kind: LimitRange
metadata:
  name: ingress-nginx
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
spec:
  limits:
  - min:
      memory: 90Mi
      cpu: 100m
    type: Container

[Configmap]nginx-configuration, tcp-services, udp-servies

두 번째는 다수의 confimap이 선언돼 있다
레이블이 세팅돼 있지만 딱히 저장돼있는 키와 값은 없다
각각의 이름은 nginx-configuration, tcp-services, udp-servies 이다

kind: ConfigMap
apiVersion: v1
metadata:
  name: nginx-configuration
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx

---
kind: ConfigMap
apiVersion: v1
metadata:
  name: tcp-services
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx

---
kind: ConfigMap
apiVersion: v1
metadata:
  name: udp-services
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx

[ServiceAccount] nginx-ingress-serviceaccount

nginx-ingress 포드에서 사용할 계정을 생성한다
쿠버네티스에서는 실행하는 앱에 권한을 줄 때 서비스 어카운트를 사용한다
서비스 어카운트에 권한을 할당해야하는데 여기서는 클러스터 롤과 롤을 할당한다
다음 코드를 정리하면 다음과 같은 권한을 할당한다
관리자 권한을 부여하지 않는 이유는 최소 권한의 원칙을 따르기 위해서이다
nginx-ingress-serviceaccount 는 다음과 같은 권한을 갖는다

apiVersion: v1
kind: ServiceAccount
metadata:
  name: nginx-ingress-serviceaccount
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
  name: nginx-ingress-clusterrole
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
rules:
  - apiGroups:
      - ""
    resources:
      - configmaps
      - endpoints
      - nodes
      - pods
      - secrets
    verbs:
      - list
      - watch
  - apiGroups:
      - ""
    resources:
      - nodes
    verbs:
      - get
  - apiGroups:
      - ""
    resources:
      - services
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - ""
    resources:
      - events
    verbs:
      - create
      - patch
  - apiGroups:
      - "extensions"
      - "networking.k8s.io"
    resources:
      - ingresses
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - "extensions"
      - "networking.k8s.io"
    resources:
      - ingresses/status
    verbs:
      - update

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: Role
metadata:
  name: nginx-ingress-role
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
rules:
  - apiGroups:
      - ""
    resources:
      - configmaps
      - pods
      - secrets
      - namespaces
    verbs:
      - get
  - apiGroups:
      - ""
    resources:
      - configmaps
    resourceNames:
      # Defaults to "<election-id>-<ingress-class>"
      # Here: "<ingress-controller-leader>-<nginx>"
      # This has to be adapted if you change either parameter
      # when launching the nginx-ingress-controller.
      - "ingress-controller-leader-nginx"
    verbs:
      - get
      - update
  - apiGroups:
      - ""
    resources:
      - configmaps
    verbs:
      - create
  - apiGroups:
      - ""
    resources:
      - endpoints
    verbs:
      - get

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
  name: nginx-ingress-role-nisa-binding
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: nginx-ingress-role
subjects:
  - kind: ServiceAccount
    name: nginx-ingress-serviceaccount
    namespace: ingress-nginx

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: nginx-ingress-clusterrole-nisa-binding
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: nginx-ingress-clusterrole
subjects:
  - kind: ServiceAccount
    name: nginx-ingress-serviceaccount
    namespace: ingress-nginx

[Deployment] nginx-ingress-controller

드디어 디플로이먼트이다
디플로이먼트는 포드를 배치한다
nginx-ingress의 역할을 하는 컨테이너를 배치하고 서비스가 동작하도록 만든다
nginx는 nginx의 conf 파일을 수정하면 프록시 서버로 동작한다
여기서는 내부 파일을 사용자가 직접 변경하지 않아도 프록시의 역할을 수행하는데
ingress를 읽는 권한이 있어서 데이터를 스스로 읽고 알맞는 서비스로 연결한다
컨테이너에서 발견할 수 있는 몇가지 특징을 표로 정리한다

구분 내용 설명
이미지 quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.30.0 커스터마이징된 nginx-ingress 이미지를 사용한다
아규먼트 /nginx-ingress-controller

--configmap=$(POD_NAMESPACE)/nginx-configuration

--tcp-services-configmap=$(POD_NAMESPACE)/tcp-services

--udp-services-configmap=$(POD_NAMESPACE)/udp-services

--publish-service=$(POD_NAMESPACE)/ingress-nginx

--annotations-prefix=nginx.ingress.kubernetes.io
앞서 쿠버네티스에 세팅한 컨피그맵들을 전달한다

네임스페이스의 이름은 ingress-nginx로 선언돼있습니다. 아규먼트에 대한 자세한 설명은 다음 링크를 참고하기 바란다

https://kubernetes.github.io/ingress-nginx/user-guide/cli-arguments/
시큐리티콘텍스트 securityContext:

allowPrivilegeEscalation: true

capabilities:

drop:

- ALL

add:

- NET_BIND_SERVICE

# www-data -> 101
runAsUser: 101
시큐리티콘텍스트는 보안 관련 설정이다
root 권한으로 실행할 수 있도록 허용했고 커널 권한은 모두 드랍하고 1024 이하의 포트를 바인딩할 수 있는 NET_BIND_SERVICE 권한만 갖게 했다
그리고 기본 애플리케이션은 www-data의 권한인 101 권한으로 실행한다
포트 ports:

- name: http

containerPort: 80

protocol: TCP

- name: https

containerPort: 443

protocol: TCP
포트는 80과 443번을 사용한다
라이브네스/레디네스 프로브 livenessProbe: (readinessProbe도 동일)

failureThreshold: 3

httpGet:

path: /healthz

port: 10254

scheme: HTTP

initialDelaySeconds: 10

periodSeconds: 10

successThreshold: 1

timeoutSeconds: 10
포드가 살아있는지 준비돼있는지 체크하는 루틴이다
10254포트로 웹 요청했을때 400미만의 요청이 오면 정상 서비스 가능한 것으로 본다
라이프사이클 lifecycle:

preStop:

exec:

command:

- /wait-shutdown
쿠버네티스도 컨테이너에 라이프사이클 훅을 제공한다
컨테이너가 생성된 직후에 실행(PostStart)되거나 컨테이너가 종료되기 직전(PreStop)에 실행할 내용을 지정할 수 있는데 여기서는 포드가 종료될 때 실행할 명령으로 wait-shutdown을 실행한다
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-ingress-controller
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: ingress-nginx
      app.kubernetes.io/part-of: ingress-nginx
  template:
    metadata:
      labels:
        app.kubernetes.io/name: ingress-nginx
        app.kubernetes.io/part-of: ingress-nginx
      annotations:
        prometheus.io/port: "10254"
        prometheus.io/scrape: "true"
    spec:
      # wait up to five minutes for the drain of connections
      terminationGracePeriodSeconds: 300
      serviceAccountName: nginx-ingress-serviceaccount
      nodeSelector:
        kubernetes.io/os: linux
      containers:
        - name: nginx-ingress-controller
          image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.30.0
          args:
            - /nginx-ingress-controller
            - --configmap=$(POD_NAMESPACE)/nginx-configuration
            - --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services
            - --udp-services-configmap=$(POD_NAMESPACE)/udp-services
            - --publish-service=$(POD_NAMESPACE)/ingress-nginx
            - --annotations-prefix=nginx.ingress.kubernetes.io
          securityContext:
            allowPrivilegeEscalation: true
            capabilities:
              drop:
                - ALL
              add:
                - NET_BIND_SERVICE
            # www-data -> 101
            runAsUser: 101
          env:
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: POD_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
          ports:
            - name: http
              containerPort: 80
              protocol: TCP
            - name: https
              containerPort: 443
              protocol: TCP
          livenessProbe:
            failureThreshold: 3
            httpGet:
              path: /healthz
              port: 10254
              scheme: HTTP
            initialDelaySeconds: 10
            periodSeconds: 10
            successThreshold: 1
            timeoutSeconds: 10
          readinessProbe:
            failureThreshold: 3
            httpGet:
              path: /healthz
              port: 10254
              scheme: HTTP
            periodSeconds: 10
            successThreshold: 1
            timeoutSeconds: 10
          lifecycle:
            preStop:
              exec:
                command:
                  - /wait-shutdown

이렇게 생성된 컨테이너는 스스로 인그레스를 읽을 수 있는 기능을 가지고 있으며 서비스 ingress-nginx를 통해서 사용된다라고 예상해볼 수 있다
또한 80포트와 443포트를 동시에 제공하고 있다


3. http-go 서비스 설치

이제 이 ingress-nginx를 직접 쿠버네티스에 설치하고 ingress가 잘 실행되는지 테스트해보자

가장 먼저 할일은 웹서비스를 하나 띄우고 그 서비스가 잘 서비스되는지 테스트하는 ingress는 그 다음에 설치한다
http-go는 go로 작성했으며 8080포트로 웹서비스를 하는 간단한 이미지이다
서비스는 NodePort로 열어준다

$ kubectl create deployment http-go --image=gasbugs/http-go
deployment.apps/http-go created

$ kubectl expose deployment http-go --port=8080 --type=NodePort
service/http-go exposed

GCP에서는 svc 포트를 확인해서 해당 포트의 방화벽 설정 추가

$ kubectl get svc
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)          AGE
http-go      NodePort    10.8.9.35    <none>        8080:31462/TCP   106s
kubernetes   ClusterIP   10.8.0.1     <none>        443/TCP          10m

$ gcloud compute firewall-rules create http-go-svc-rule --allow=tcp:31462
Creating firewall...⠹Created [https://www.googleapis.com/compute/v1/projects/freework-gke-test-20201227/global/firewalls/http-go-svc-rule].
Creating firewall...done.
NAME              NETWORK  DIRECTION  PRIORITY  ALLOW      DENY  DISABLED
http-go-svc-rule  default  INGRESS    1000      tcp:31462        False

테스트를 위해 EXTERNAL-IP 정보 확인

 kubectl get nodes -o wide
NAME                                       STATUS   ROLES    AGE   VERSION             INTERNAL-IP   EXTERNAL-IP     OS-IMAGE                             KERNEL-VERSION   CONTAINER-RUNTIME
gke-cluster-1-default-pool-3496da67-fh9n   Ready    <none>   13m   v1.16.15-gke.6000   10.128.0.5    34.72.1.248     Container-Optimized OS from Google   4.19.112+        docker://19.3.1
gke-cluster-1-default-pool-3496da67-nlsd   Ready    <none>   13m   v1.16.15-gke.6000   10.128.0.6    35.239.62.20    Container-Optimized OS from Google   4.19.112+        docker://19.3.1
gke-cluster-1-default-pool-3496da67-zfjd   Ready    <none>   13m   v1.16.15-gke.6000   10.128.0.7    35.184.60.185   Container-Optimized OS from Google   4.19.112+        docker://19.3.1

잠시 후 웹서비스가 잘 도는지 확인하기 위해서 curl 명령을 사용한다

$ curl 34.72.1.248:31462
Welcome! http-go-78dfc8fcf5-d2xbb

4. Ingress-nginx 설치

https://github.com/kubernetes/ingress-nginx/blob/master/docs/deploy/index.md

이제 앞서 분석했던 yaml을 사용해 ingress-nginx를 설치한다
분석했던 내용처럼 namespace가 생성되고 configmap 3개, 서비스어카운트에 클러스터롤과 롤 권한이 부여된다
마지막으로 nginx-ingress-controller라는 이름으로 디플로이먼트가 시작된다

https://github.com/kubernetes/ingress-nginx/blob/master/docs/deploy/index.md#bare-metal

$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.43.0/deploy/static/provider/baremetal/deploy.yaml
namespace/ingress-nginx created
serviceaccount/ingress-nginx created
configmap/ingress-nginx-controller created
clusterrole.rbac.authorization.k8s.io/ingress-nginx created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx created
role.rbac.authorization.k8s.io/ingress-nginx created
rolebinding.rbac.authorization.k8s.io/ingress-nginx created
service/ingress-nginx-controller-admission created
service/ingress-nginx-controller created # deployment 를 사용할 수 있도록 열어줌
deployment.apps/ingress-nginx-controller created # deployment 를 생성했음
validatingwebhookconfiguration.admissionregistration.k8s.io/ingress-nginx-admission created
serviceaccount/ingress-nginx-admission created
clusterrole.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
role.rbac.authorization.k8s.io/ingress-nginx-admission created
rolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
job.batch/ingress-nginx-admission-create created
job.batch/ingress-nginx-admission-patch created

ingress-nginx-controller 서비스 확인
ingress 파일을 읽어서 http-go 로 연결해준다

$ kubectl get service/ingress-nginx-controller -n ingress-nginx
NAME                       TYPE       CLUSTER-IP   EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx-controller   NodePort   10.8.0.3     <none>        80:31170/TCP,443:32188/TCP   3m34s

ingress-nginx 네임스페이스의 포드를 조회해 잘 도는지 확인한다
당연히 지금은 ingress 객체를 만들지 않았기 때문에 포워딩 기능이 실행되고 있지는 않다

$ kubectl get pod -n ingress-nginx
NAME                                        READY   STATUS    RESTARTS   AGE
nginx-ingress-controller-7f74f657bd-m4sjb   1/1     Running   0          99s

함께 만들어진 nginx-ingress-controller의 서비스인 노드포트를 확인한다
여기서 포트는 31042와 30947이다
443 포트는 ingress를 생성했을 때 tls를 쓴 경우에 사용할 수 있다
여기서는 80포트로 접속할 것이니 31042를 사용하면 된다

$ kubectl get svc -n ingress-nginx
NAME                       TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
nginx-ingress-controller   NodePort   10.96.254.175   <none>        80:31042/TCP,443:30947/TCP   56s

5. Ingress 룰 생성

이제 ingress를 생성해 ingress-nginx와 http-go를 연결할 룰을 만들어 준다
다음 그림처럼 룰을 만들어야 외부에서 요청이 왔을 때 인그레스가 http-go로 포워딩해준다
ingress의 룰은 단순하다
도메인과 경로로 규칙을 지정하는데 여기서는 gasbugs.com/hostsname로 ingress에 요청이 들어오면 http-go로 연결해준다

내용을 작성할 때는 다음을 주의해야 합니다

  • http-go와 동일한 네임스페이스에 작성해야 함
  • 앞서 생성한 서비스 이름이 serviceName과 동일해야 함
  • servicePort는 서비스가 동작하는 포트를 의미해야 함
    (서비스의 포트와 포드의 포트가 다른 경우에도 서비스 포트를 적는다)

도메인 이름은 gasbugs.com을 사용하고 /hostsname 경로를 사용하도록 만들었기 때문에
반드시 http://gasbugs.com/hostsname으로 요청해야만 http-go로 연결된다

http-go-ingress.yaml 파일 생성

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: http-go-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: gasbugs.com
    http:
      paths:
      - path: /hostname
        backend:
          serviceName: http-go
          servicePort: 8080

kubectl 로 ingress 생성

$ kubectl create -f http-go-ingress.yaml
ingress.extensions/http-go-ingress created

ingress-nginx-controller 서비스를 조회해서 포트 확인 후 방화벽 오픈

$ kubectl get svc -n ingress-nginx ingress-nginx-controller
NAME                       TYPE       CLUSTER-IP   EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx-controller   NodePort   10.8.0.3     <none>        80:31170/TCP,443:32188/TCP   10m

$ gcloud compute firewall-rules create ingress-svc-rule --allow=tcp:31170
Creating firewall...⠹Created [https://www.googleapis.com/compute/v1/projects/freework-gke-test-20201227/global/firewalls/ingress-svc-rule].
Creating firewall...done.
NAME              NETWORK  DIRECTION  PRIORITY  ALLOW      DENY  DISABLED
ingress-svc-rule  default  INGRESS    1000      tcp:31170        False

6. 인그레스 정상 동작 테스트

GCP 에서 동작 확인

IP 확인

kubectl get nodes -o wide
NAME                                       STATUS   ROLES    AGE   VERSION             INTERNAL-IP   EXTERNAL-IP     OS-IMAGE                             KERNEL-VERSION   CONTAINER-RUNTIME
gke-cluster-1-default-pool-3496da67-fh9n   Ready    <none>   35m   v1.16.15-gke.6000   10.128.0.5    34.72.1.248     Container-Optimized OS from Google   4.19.112+        docker://19.3.1
gke-cluster-1-default-pool-3496da67-nlsd   Ready    <none>   35m   v1.16.15-gke.6000   10.128.0.6    35.239.62.20    Container-Optimized OS from Google   4.19.112+        docker://19.3.1
gke-cluster-1-default-pool-3496da67-zfjd   Ready    <none>   35m   v1.16.15-gke.6000   10.128.0.7    35.184.60.185   Container-Optimized OS from Google   4.19.112+        docker://19.3.1

curl 접속 테스트시 도메인 이름과 URI 가 일치 해야지만 연결을 해주는데 일치하지 않으므로 연결이 실패함

$ curl 34.72.1.248:31170
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx</center>
</body>
</html>

/etc/hosts 에 도메인 추가

$ sudo vi /etc/hosts
...
34.72.1.248 gasbugs.com

path 의 /hostname URI 까지 일치 시키면 연결이 성공함

$ curl gasbugs.com:31170/hostname
Welcome! http-go-78dfc8fcf5-d2xbb

local 에서 동작 확인

gasbugs.com의 31042로 접속을 시도해보자
127.0.0.1:31042 로도 요청을 수행한다
127.0.0.1을 직접 요청하는 경우에는 도메인이름이 "127.0.0.1"로 날아가기 때문에 앞서 설정한 룰과 일치하지 않아서 404를 띄운다

$ curl gasbugs.com:31042
curl: (6) Could not resolve host: gasbugs.com

$ curl 127.0.0.1:31042
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.17.8</center>
</body>
</html>

두 요청 모두 제대로된 응답을 못받는다
우리는 도메인을 등록한 적이 없기 때문인데 도메인을 등록해서 해결하기보다는
임시용으로 /etc/hosts에 "127.0.0.1 gasbugs.com"를 추가하도록 한다

$ sudo vim /etc/hosts
127.0.0.1       gasbugs.com
<생략>

다시 요청을 수행한다
여전히 페이지를 못 찾는 모습을 보인다
경로도 정확하게 입력해야 한다

$ curl gasbugs.com:31042
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.17.8</center>
</body>
</html>

이번에는 도메인 이름과 경로를 모두 일치시켜서 질의를 수행하면 정상적으로 응답을 받아오는 모습을 관찰할 수 있다

$ curl gasbugs.com:31042/hostname
Welcome! http-go-78dfc8fcf5-jzmmv
728x90

댓글

💲 추천 글