[쿠버네티스 DevOps 구축] - Ingress Nginx Controller 설치하기

목차

참고

Ingress Controller 설치

현재 설치된 쿠버네티스에서는 Ingress 를 생성 하더라도 외부 요청을 Ingress 설정에 맞게 외부 요청을 내부 서비스로 전달해주는 Controller 가 따로 없습니다. 다시 말해, 규칙을 생성하더라도 규칙을 읽어서 적용시켜주는 모듈이 없는 상태입니다.

보통, 클라우스 서비스에서는 ALB 나 NLB 와 같은 서비스를 이용해 Ingress 정책을 읽어 Load Balancing 규칙을 적용해주는데, 개인 쿠버네티스 서비스에서는 저런 시스템을 기대하기 힘듦으로 저는 Nginx 에서 제공해주는 Ingress Controller 를 이용하려고 합니다.

Helm 설치

helm upgrade --install ingress-nginx ingress-nginx \
--repo https://kubernetes.github.io/ingress-nginx \
--namespace ingress-nginx --create-namespace

BareMetal 설치

# BareMetal 설치
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.0.4/deploy/static/provider/baremetal/deploy.yaml
kubectl apply -f deploy.yaml

# Cloud 설치
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.0/deploy/static/provider/cloud/deploy.yaml
kubectl apply -f 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

1. hostNetwork 사용하기

EKS 나 AKS 와는 달리 LB(Load Balancer) 가 없는 Bare Metal 환경에서는 Ingress Controller 만 설치 했다고 해서 외부 요청이 쿠버네티스 내로 들어오지는 못합니다. 😭

NortPort 를 이용해 Ingress Controller 의 서비스를 외부로 노출하는 방법이 있지만, 단일 Pod 만 올린 상태라 Pod 의 포트를 외부로 직접 노출하는 hostNetwork 를 사용하려고 합니다. (hostPort 도 사용 가능)

hostNetwork 옵션을 사용하면, 해당 Pod가 노드의 네트워크 네임스페이스를 공유하게 되어 컨테이너 포트가 노드 포트와 직접 연결됩니다. 즉, 컨테이너 내의 80번 포트가 자동으로 노드의 80번 포트와 바인딩되므로 별도의 포트 포워딩 없이 외부에서 노드의 80번(및 443번) 포트로 접속할 때 Ingress Controller 가 요청을 처리하게 됩니다.

만일 Controller Pod 가 여러개 있어 쿠버네티스의 서비스에서 제공하는 로드밸런싱을 사용하고 싶다면 NortPort 를 이용해 외부에서 접근하도록 설정하면 됩니다.

apiVersion: apps/v1
kind: Deployment
metadata:
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: ingress-nginx
template:
metadata:
labels:
app.kubernetes.io/name: ingress-nginx
spec:
# hostNetwork 활성화: Pod가 노드 네트워크를 사용함 수 있습니다.
hostNetwork: true
containers:
- name: controller
image: k8s.gcr.io/ingress-nginx/controller:v1.7.1
args:
- /nginx-ingress-controller
# 필요에 따라 추가 인자 설정
ports:
- name: http
containerPort: 80
# hostNetwork 사용 시 hostPort 지정은 사실상 불필요하지만 명시할 수도 있음
hostPort: 80
protocol: TCP
- name: https
containerPort: 443
hostPort: 443
protocol: TCP

HTTPS 적용하기 - NGINX Ingress Controller와 cert-manager

Ingress Controller 설치를 통해 클러스터내부와 외부의 HTTP 통신이 가능한 상태니 여기서 보안이 추가된 HTTPS 통신을 하기 위한 설정을 하려고 합니다.

HTTPS 를 사용하기 위해서는 인증서를 생성하고 GlobalSign 나 DigiCert 와 같은 신뢰성이 높고 유명한 기관에 인증서를 등록해야 하지만, 기관에 SSL 인증서를 등록하기 위해서는 금액이 꽤 들기 때문에 무료로 인증서를 등록 및 관리하는 방법이 없는지 찾아보다가 쿠버네티스에서 HTTPS 를 손쉽게 적용해주는 cert-manager 를 찾았습니다.

cert-manager 에서는 쿠버네티스에서 쉽게 HTTPS 를 구성할 수 있도록 Operator 를 제공합니다.

1. cert-manager 설치

kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.15.3/cert-manager.yaml

2. Issuers 정의

# tls-issuer.yaml
# kubectl apply -f tls-issuer.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-nginx
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: <이메일>
privateKeySecretRef:
name: letsencrypt-nginx
solvers:
- http01:
ingress:
class: nginx

3. ingress에 반영

# ingress.yaml
# kubectl apply -f ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
cert-manager.io/cluster-issuer: letsencrypt-nginx
acme.cert-manager.io/http01-edit-in-place: "true"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
kubernetes.io/tls-acme: "true"
name: backend-ingress
namespace: default
spec:
ingressClassName: "nginx"
tls:
- hosts:
- <도메인>
secretName: tls-secret
rules:
- host: <도메인>
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: backend-svc
port:
number: 80
Share