이제 nginx ingress를 직접 구성해보자. ingress에 대한 개념은 [k8s] Ingress의 개념과 트레픽 흐름 포스팅을 참고하기 바란다.

Ingress는 Ingress Controller를 통해서 실행된다. Ingress-Nginx Controller 를 먼저 설치해보자. Ingress-Nginx Controller는 k8s 버전 마다 지원되는 버전이 다르다. 2024년 12월 기준으로 ingress-nginx 버전별 k8s 지원 버전은 다음과 같다. 더 자세한 내용은 "[k8s] Ingress의 개념과 트레픽 흐름"포스팅을 참고하면 된다.

현재 테스트 서버의 k8s 버전은 1.31.1 이므로 ingress-nginx 1.12.0을 설치하겠다.
### k8s 버전 확인
# k get nodes
NAME STATUS ROLES AGE VERSION
kjh-m1 Ready control-plane 24d v1.31.1
kjh-m2 Ready control-plane 24d v1.31.1
kjh-m3 Ready control-plane 24d v1.31.1
kjh-w1 Ready worker 23d v1.31.1
kjh-w2 Ready worker 23d v1.31.1
### nginx-ingress controller 설치
# kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.12.0-beta.0/deploy/static/provider/baremetal/deploy.yaml
설치 결과 ingress-nginx 네임스페이스가 생성되었고, 그 안에 ingress-nginx 관련 리소스가 생성된 것을 확인할 수 있다.
# k get namespace ingress-nginx
NAME STATUS AGE
ingress-nginx Active 7m39s
# k get all -n=ingress-nginx
root@kjh-m1:~# k get all -n=ingress-nginx
NAME READY STATUS RESTARTS AGE
pod/ingress-nginx-admission-create-2gltg 0/1 Completed 0 7m54s
pod/ingress-nginx-admission-patch-mvwgn 0/1 Completed 0 7m54s
pod/ingress-nginx-controller-8688dd9bfc-zzk66 1/1 Running 0 7m54s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/ingress-nginx-controller NodePort 10.233.19.196 <none> 80:32244/TCP,443:31810/TCP 8m1s
service/ingress-nginx-controller-admission ClusterIP 10.233.58.193 <none> 443/TCP 7m55s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/ingress-nginx-controller 1/1 1 1 7m56s
NAME DESIRED CURRENT READY AGE
replicaset.apps/ingress-nginx-controller-8688dd9bfc 1 1 1 7m56s
NAME STATUS COMPLETIONS DURATION AGE
job.batch/ingress-nginx-admission-create Complete 1/1 56s 7m56s
job.batch/ingress-nginx-admission-patch Complete 1/1 57s 7m56s
ingress-nginx-controller는 Deployment → ReplicaSet → Pod 순서로 배포 및 관리하고 있다.
# k describe deployment.apps/ingress-nginx-controller -n=ingress-nginx |tail -5
NewReplicaSet: ingress-nginx-controller-8688dd9bfc (1/1 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 20m deployment-controller Scaled up replica set ingress-nginx-controller-8688dd9bfc to 1
# k describe replicasets.apps/ingress-nginx-controller-8688dd9bfc -n=ingress-nginx |tail -4
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulCreate 21m replicaset-controller Created pod: ingress-nginx-controller-8688dd9bfc-zzk66
# k describe pod/ingress-nginx-controller-8688dd9bfc-zzk66 -n=ingress-nginx |tail -12
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 22m default-scheduler Successfully assigned ingress-nginx/ingress-nginx-controller-8688dd9bfc-zzk66 to kjh-w1
Warning FailedMount 22m (x7 over 22m) kubelet MountVolume.SetUp failed for volume "webhook-cert" : secret "ingress-nginx-admission" not found
Normal Pulling 21m kubelet Pulling image "registry.k8s.io/ingress-nginx/controller:v1.12.0-beta.0@sha256:9724476b928967173d501040631b23ba07f47073999e80e34b120e8db5f234d5"
Normal Pulled 20m kubelet Successfully pulled image "registry.k8s.io/ingress-nginx/controller:v1.12.0-beta.0@sha256:9724476b928967173d501040631b23ba07f47073999e80e34b120e8db5f234d5" in 38.739s (38.739s including waiting). Image size: 292505050 bytes.
Normal Created 20m kubelet Created container controller
Normal Started 20m kubelet Started container controller
Normal RELOAD 20m nginx-ingress-controller NGINX reload triggered due to a change in configuration
Warning Unhealthy 20m kubelet Readiness probe failed: HTTP probe failed with statuscode: 500
Warning Unhealthy 20m kubelet Liveness probe failed: HTTP probe failed with statuscode: 500
배포된 controller pod의 이미지를 확인해보면 1.12.0 버전이 배포된 것을 확인 할 수 있다.
# kubectl describe pod/ingress-nginx-controller-8688dd9bfc-zzk66 -n ingress-nginx | grep "Image:"
Image: registry.k8s.io/ingress-nginx/controller:v1.12.0-beta.0@sha256:9724476b928967173d501040631b23ba07f47073999e80e34b120e8db5f234d5
서비스는 Ingress 리소스를 통해 클러스터 외부로부터 들어오는 HTTP(S) 트래픽을 처리하기 한다. NodePort 타입으로 클러스터 외부에서 노드의 특정 포트(80:32244와 443:31810)로 접근 가능하도록 설정되었다.
참고로 ingress-nginx-controller-admission 서비스는 Ingress 리소스를 생성하거나 수정할 때 Validating Webhook(Ingress 리소스의 유효성을 검사하고 올바른 구성을 보장하는 역할)을 수행한다.
# k get service -n=ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller NodePort 10.233.19.196 <none> 80:32244/TCP,443:31810/TCP 14m
ingress-nginx-controller-admission ClusterIP 10.233.58.193 <none> 443/TCP 14m
ingress class는 ingress class는 하나의 클러스터에서 여러 인그레스 컨트롤러를 사용할 수 있도록 하기 위해 만들어진 API 리소스이다.
즉 실제 ingress는 하나의 인그레스 클래스와 연결된다. 그리고 그 인그레스 클래스가 사용하는 인그레스 컨트롤러를 통해서 규칙이 정해진다.
ingress class를 확인해보면 이름은 nginx이다. ingress 규칙을 생성할때 이 ingress class 이름을 명시한다. 그러면 ingress 규칙은 같은 ingress class를 가지고 있는 ingress controller와 연동된다.
root@kjh-m1:~/ingress-test# k get ingressclasses.networking.k8s.io
NAME CONTROLLER PARAMETERS AGE
nginx k8s.io/ingress-nginx <none> 31m
root@kjh-m1:~/ingress-test# k get ingressclasses.networking.k8s.io -o yaml
apiVersion: v1
items:
- apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"networking.k8s.io/v1","kind":"IngressClass","metadata":{"annotations":{},"labels":{"app.kubernetes.io/component":"controller","app.kubernetes.io/instance":"ingress-nginx","app.kubernetes.io/name":"ingress-nginx","app.kubernetes.io/part-of":"ingress-nginx","app.kubernetes.io/version":"1.12.0-beta.0"},"name":"nginx"},"spec":{"controller":"k8s.io/ingress-nginx"}}
creationTimestamp: "2024-12-29T06:10:39Z"
generation: 1
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.12.0-beta.0
name: nginx
resourceVersion: "4985915"
uid: 6609e0c8-e332-4d57-bcb3-ac8a65a47930
spec:
controller: k8s.io/ingress-nginx
kind: List
metadata:
resourceVersion: ""
# k get deployment.apps/ingress-nginx-controller -n=ingress-nginx -o yaml |grep -i ingress-class |tail -1
- --ingress-class=nginx
ingress 테스트에 필요한 서비스 3개를 배포하자. 서비스의 yml 파일은 다음과 같다.
# cat ingress-test/grafana/deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: grafana
labels:
app: "grafana"
spec:
replicas: 1
selector:
matchLabels:
app: "grafana"
template:
metadata:
labels:
app: "grafana"
spec:
containers:
- name: grafana
image: grafana/grafana:latest
ports:
- name: http
containerPort: 3000
# cat ingress-test/grafana/service.yml
apiVersion: v1
kind: Service
metadata:
name: grafana
labels:
app: "grafana"
spec:
type: ClusterIP
ports:
- name: http
protocol: TCP
port: 80
targetPort: 3000
selector:
app: "grafana"
# cat ingress-test/httpd/deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpd
labels:
app: "httpd"
spec:
replicas: 1
selector:
matchLabels:
app: "httpd"
template:
metadata:
labels:
app: "httpd"
spec:
containers:
- name: httpd
image: httpd:latest
ports:
- name: http
containerPort: 80
# cat ingress-test/httpd/service.yml
apiVersion: v1
kind: Service
metadata:
name: httpd
labels:
app: "httpd"
spec:
type: ClusterIP
ports:
- name: http
protocol: TCP
port: 80
targetPort: 80
selector:
app: "httpd"
# cat ingress-test/hello/deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello
spec:
replicas: 3
selector:
matchLabels:
app: hello
template:
metadata:
name: hello
labels:
app: hello
spec:
containers:
- name: nginx
image: nginxdemos/hello:plain-text
ports:
- name: http
containerPort: 80
protocol: TCP
# cat ingress-test/hello/service.yml
apiVersion: v1
kind: Service
metadata:
name: hello
labels:
app: hello
spec:
type: ClusterIP
ports:
- name: http
protocol: TCP
port: 8080
targetPort: 80
selector:
app: hello
각 서비스를 배포해보자.
# cd ~/ingress-test
# k apply -f grafana/
deployment.apps/grafana created
service/grafana created
# k apply -f httpd/
deployment.apps/httpd created
service/httpd created
# k apply -f hello/
deployment.apps/hello created
service/hello created
ingress 규칙을 설정하는 방법은 여러 방법이 있는데 그 중에 path, host, defaultBackend를 이용한 구성 방법을 살펴보자.
ingress 규칙은 다음과 같다.
# cat ingress-path.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: path
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- http:
paths:
- path: /hello
pathType: Prefix
backend:
service:
name: hello
port:
name: http
- http:
paths:
- path: /grafana
pathType: Prefix
backend:
service:
name: grafana
port:
name: http
설정 파일은 다음과 같이 정의되어 있다.
[1] ingress-nginx conrotller 설치 가이드
https://kubernetes.github.io/ingress-nginx/deploy/#bare-metal-clusters
[2] ingress-nginx controller 버전별 호환 k8s 버전
https://github.com/kubernetes/ingress-nginx/blob/main/README.md#supported-versions-table
[3] ingress 테스트 예제
https://velog.io/@pinion7/Kubernetes-%EB%A6%AC%EC%86%8C%EC%8A%A4-Ingress%EC%97%90-%EB%8C%80%ED%95%B4-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B3%A0-%EC%8B%A4%EC%8A%B5%ED%95%B4%EB%B3%B4%EA%B8%B0