Ingress의 모든것
July 2023 (1406 Words, 8 Minutes)
Ingress의 모든것
안녕하세요 오늘은 쿠버네티스에서 사용되는 Ingress의 개념과, Ingress Controller에서 사용되는 것들을 다루어 보겠습니다. 최초 설치 및 진행을 위해 Ingress Nginx Controller의 설치와 Ingress 설정 방법 및 애드온들에 대해 설명해드리겠습니다.
심도있는 내용을 다루는것도 좋지만, 기본기를 다루는 내용도 조금 다뤄보고자합니다.
Ingress
Ingress는 쿠버네티스 리소스로, 쿠버네티스 클러스터에서 실행되는 애플리케이션에 대한 HTTP 로드 밸런서를 구성할 수 있게 해주는 역할을 합니다. 이 로드 밸런서를 통해 쿠버네티스 클러스터 외부의 클라이언트들은 애플리케이션에 접근할 수 있습니다.
Ingress는 클러스터 외부에서 클러스터 내부의 서비스로 네트워크 트래픽을 관리하는 API 객체입니다. 이를 통해 외부에서 접근하는 URL 경로, IP 주소 또는 도메인에 따라 특정 서비스로 트래픽을 라우팅하는 규칙을 설정할 수 있습니다.
Ingress는 라우팅 규칙만 정의하기 때문에 규칙을 실제로 적용하고 트래픽을 관리하기 위해서는 별도의 Ingress Controller가 필요합니다. 이 때문에, Ingress Controller는 Ingress가 설정한 라우팅 규칙을 실제로 실행하여, 외부의 클라이언트들이 정해진 규칙에 따라 쿠버네티스 내부의 서비스로 트래픽이 라우팅되도록 하는 역할을 수행합니다.
Ingress Controller
Ingress 컨트롤러는 클러스터에서 실행되는 애플리케이션으로, Ingress 리소스에 따라 HTTP 로드 밸런서를 구성하는 역할을 합니다. Ingress Nginx Controller는 이 중 하나로, Kubernetes의 Ingress 리소스를 이용하여 HTTP와 HTTPS 라우팅을 처리합니다. 이 컨트롤러는 Ingress 리소스에 정의된 라우팅 규칙을 실제로 적용하고, Nginx를 사용하여 클라이언트의 요청을 적절한 서비스로 라우팅합니다. 추가로, SSL 종단간 암호화, 세션 별 로드 밸런싱, 웹소켓 지원, 그리고 Annotation을 통한 세밀한 설정도 가능합니다.
Ingress는 클러스터 외부의 네트워크 트래픽을 클러스터 내부의 서비스로 관리하는 API 오브젝트입니다. 이를 이용하면 외부에서 접근하는 URL 경로, IP 주소 또는 도메인에 따라 특정 서비스로 트래픽을 라우팅할 수 있습니다.
Ingress Nginx Controller 설치하기
설치는 Helm으로 진행하며 설치가 안되어있다면 해당 명령어로 설치가 가능합니다.
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
chmod 700 get_helm.sh
./get_helm.sh
설치할 Ingress Nginx Controller의 최신버젼은
https://github.com/kubernetes/ingress-nginx
공식 git 에서 확인 할 수 있지만, 설치를 git에서 직접 하는것이 아닌 helm을 이용해 설치하기 때문에, helm repo의 최신버젼 이미지에서 확인할 수 있습니다.
게시글을 작성하는 23.07.23 기준으론 git의 최신버젼 이미지가 v1.8.1이고
git에서 직접 표시하고있는 helm chart version 에서도 4.7 버젼대 helm 설치를 진행하면 v.1.8.1로 설치가 가능하다고 안내하고 있습니다.
하지만 위 그림처럼 git에서 helm 배포 버젼까지 친절하게 안내해주는 경우는 잘 없습니다. 심지어 공식 helm 배포가 이루어지지 않아, 사용자가 helm 을 이용하게 제작해 helm 에 등록하는 경우도 있으니 조금 더 까다로울수 있어도, helm value 파일만 있으면 버젼 관리를 편하게 할 수 있고, 업데이트 및 롤백도 간단하게 할 수 있는 이점들이 있습니다.
설치할 helm chart는 일반적으로 artifact hub에서 찾을 수 있습니다
ingress-nginx 4.7.1 · kubernetes/ingress-nginx
helm은 install 명령어 한줄로도 기본값인 default value로 패키지 설치가 가능합니다.
위에 첨부한 artifact hub에서 Default values를 눌러보면 설치에 이용될 기본 값들을 확인 할 수 있습니다.
하지만 default value 외에 별도로 변경 하고싶은 값이 있다면, 별도로 변경할 값들만 담은 custom value 파일을 만들어 helm 패키지 설치를 할 수 있습니다.
controller:
service:
type: NodePort
httpPorts:
- name: http
port: 80
targetPort: 80
nodePort: 31071
- name: https
port: 443
targetPort: 80
nodePort: 32054
metrics:
enabled: true
prometheusRule:
enabled: true
defaultBackend:
enabled: true
위는 제가 온프레미스에서 사용하기 적합한 데이터들로 구성한 ingress nginx controller의 helm 설치를 위한 custom value 파일입니다.
ingress controller를 nodeport로 노출하면서 별도 포트를 직접 지정해주지않는다면 kube-apiserver에서 할당 가능한 무작위 port (기본적으로 30000-32767)중에 할당이 됩니다. 매번 변경되는 nodeport보다 무작위 숫자더라도 직접 명시해서 관리하는 것이 좋다고 생각해 설정했습니다.
나머지 값들은 제 환경에 적합하게 사용 될 수 있는 값들이기 때문에, 활성화를 했습니다.
해당 값들에 대한 기본설정들은 여전히 default values에 담겨져있으며Untitled, 필요하다면 수정을 해도 무관합니다.
custom value 파일에 대한 설명을 이만 마치고, 다시 helm 설치를 진행하겠습니다.
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
helm install my-ingress-nginx ingress-nginx/ingress-nginx --version 4.7.1
helm repository 에 올라와있는 설치 명령어입니다.
설치 환경에서 repo add 를 진행 후, install을 진행하는데, 다음과 같은 명령어로 설치를 진행 할 경우 기본 값으로만 설치가 진행됩니다.
제가 애용하는 명령어는
helm upgrade --install my-ingress-nginx ingress-nginx/ingress-nginx --version 4.7.1 -f cvalues.yaml -n ingress-nginx
와 같은 설치 명령어입니다.
기존에 설치했던 value와 변경이 될때 새로 변경점을 적용하면서 helm 의 새로운 revision을 생성하고, 내가 작성했던 value 파일과, 설치를 진행하고 싶은 namespace에 프로비저닝하는 명령어입니다.
설치를 진행하고나면 위와같이 설치가 완료된것을 확인 할 수 있습니다.
쿠버네티스 외부 네트워크 설정 - 외부
ingress 는 도메인 기반으로 동작하기때문에, Route53등에 등록하려는 도메인을 내 public ip로 등록을 해주어야 합니다.
예를들면 현재 보고있는 블로그는 blog.montkim.com 도메인이며, 해당 도메인으로 입력을 받으면 집의 public ip로 리다이렉팅 해줍니다.
Route53에 도메인기반으로 등록하는 ip는 http / https가 각각 80 / 443 포트로만 리다이렉팅이 됩니다.
이후에 설정할 로컬 네트워크에서는 수신한 80/443 포트에 대해서 처리할 수 있어야 합니다.
쿠버네티스 외부 네트워크 설정 - 로컬
위의 외부설정을 통해 blog.montkim.com 요청을 받으면 제 집 IP의 80/443 포트로 접속을시도합니다.
제 집 IP 는 하나지만, 그 안에 있는 여러 개의 장비 중, 쿠버네티스가 설치되어있는 노드의 IP로 연결을 해주어야 합니다.
이를 위해 포트포워딩을 해주며, 포트포워딩을 할 수 있는 구체적인 방법은 각 인터넷환경에 따라 다릅니다.
내 쿠버네티스 서버의 IP가 192.168.0.1 이라고 할 때
네트워크 장비의 설정에서
public ip 의 80 / 443 포트로 입력을 받으면
192.168.0.1 31071/32054 포트로 포워딩을 시켜주어야 합니다
이렇게되면 웹에서 도메인을 입력했을때 Route53에서 집의 public ip로 변환이 이루어지고, 이 요청은 ingress nginx controller로 수신됩니다.
IngressClass
IngressClass는 Kubernetes의 리소스 중 하나로, Ingress 리소스의 동작을 구성하는 데 사용됩니다. 이는 특히 동일한 Kubernetes 클러스터에서 여러 Ingress 컨트롤러를 사용할 때 유용합니다.
IngressClass 리소스는 특정 클래스의 Ingress 리소스가 사용할 Ingress 컨트롤러를 지정합니다. 예를 들어, 하나의 클러스터에 NGINX Ingress 컨트롤러와 Traefik Ingress 컨트롤러가 모두 있는 경우, IngressClass를 사용하여 각 Ingress 리소스가 어떤 컨트롤러를 사용할지 결정할 수 있습니다.
이를 통해, 각 Ingress 리소스는 클래스 이름을 참조하여 해당 클래스의 Ingress 컨트롤러에 의해 처리됩니다. 이는 spec.ingressClassName
필드에 클래스 이름을 지정함으로써 이루어집니다.
IngressClass에는 또한 parameters
필드가 있어, 이를 통해 Ingress 컨트롤러의 구성에 대한 세부 사항을 지정할 수 있습니다.
Kubernetes 1.18 이전에서는 Ingress 리소스의 kubernetes.io/ingress.class
주석(annotation)을 사용하여 이 기능을 제공하였습니다. 하지만 Kubernetes 1.18 이후부터는 IngressClass API를 이용하여 더 정교하게 이 기능을 사용할 수 있게 되었습니다.
helm 으로 ingress nginx controller를 설치하면 기본적으로 “nginx”라는 ingressclass가 생성됩니다.
이 ingressclass에 대해서 다루는 이유는 ingress 파일을 생성할때 ingress controller로 맵핑을 위해 ingressclass를 지정해 ingress 를 작성 합니다.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: jekyll-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: blog.montkim.com
과거엔 이런 형식과 같이 annotation에 ingressclass를 넣어 줄수도있지만, 새로 ingress class를 지정하는 방법이 생겼습니다.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: jekyll-ingress
annotations:
spec:
ingressClassName: nginx
rules:
- host: blog.montkim.com
metadata.annotation에서 spec.ingressClassName 항목으로 변경되어 직접 지정이 가능해졌습니다.
Cert Manager
Cert Manager는 Kubernetes에서 자동화된 SSL/TLS 인증서 관리를 제공하는 addon 입니다. Cert Manager는 Let’s Encrypt와 같은 인증 기관(ACME)으로부터 인증서를 자동으로 발급하고, 갱신하는 기능을 제공합니다.
- 자동 인증서 발급: Cert Manager는 Kubernetes의 CertificateRequest 리소스를 사용하여 인증서를 자동으로 발급할 수 있습니다. 이를 통해 사용자는 수동으로 인증서를 발급하거나 갱신할 필요가 없습니다.
- 인증서 갱신: Cert Manager는 인증서의 유효 기간이 만료되기 전에 자동으로 인증서를 갱신합니다. 이는 인증서 만료로 인한 서비스 중단을 방지합니다.
- Ingress 통합: Cert Manager는 Kubernetes의 Ingress 리소스와 통합되어, 애플리케이션에 SSL/TLS 인증서를 쉽게 제공할 수 있습니다. Ingress 리소스에 어노테이션을 추가하면, Cert Manager는 해당 서비스에 대한 인증서를 자동으로 발급하고, Ingress 리소스를 업데이트하여 트래픽이 해당 인증서를 사용하도록 합니다.
- Certificate 표준 리소스 사용: Cert Manager는 쿠버네티스의 Certificate, CertificateRequest, Issuer, ClusterIssuer 등의 리소스를 사용하여 인증서를 관리합니다. 이를 통해 쿠버네티스 API를 사용하여 인증서의 Lifecycle을 관리할 수 있습니다.
Cert Manager는 Kubernetes에서 SSL/TLS 인증서 관리를 단순화하고, 자동화하므로, 사용자는 보안에 대한 걱정 없이 애플리케이션에 집중할 수 있습니다.
그러면 빠르고 간단하게 Cert Manger설치하는 방법을 다루고 다음단계로 넘어가겠습니다.
helm repo add cert-manager https://charts.jetstack.io
helm repo update
helm upgrade --install my-cert-manager cert-manager/cert-manager --version 1.12.2 -n cert-manager --create-namespace --set installCRDs=true
cert manager 공식 helm repo에서 받아온 이미지로 설치를 진행합니다.
별도로 value 파일을 작성할 필요없이 파라미터로 install CRD만 활성화 했기때문에 저 명령어대로 설치를 진행합니다.
Cluster Issuer
Cert Manager를 사용하려면, Issuer 또는 ClusterIssuer를 생성해야 합니다. Cert Manager가 인증서를 발급하기 위해 사용하는 구성 요소 입니다. ClusterIssuer는 클러스터 전체의 모든 네임스페이스에서 인증서를 발급할 수 있습니다.
예를 들어, Let’s Encrypt를 사용하는 ClusterIssuer를 생성하려면 다음과 같은 YAML 파일(cluster-issuer.yaml
)을 만들어 kubectl로 적용합니다:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: your-email@example.com
privateKeySecretRef:
name: letsencrypt-prod
solvers:
- http01:
ingress:
class: nginx
위와같이 cluster issuer를 발급하고나면, ingress 를 생성할 때 annotation에 cluster-issuer를 적어줌으로서 발급하고자 하는 ingress에 대한 https let’s encrypt 인증서를 발급 받을 수 있습니다.
최종본 Ingress 생성하기
위에 다루었던 인프라를 구축해 도메인을 입력했을때 제 환경의 클러스터로 리다이렉팅이 되게 셋팅을 해두었고, ingress nginx controller를 통해 ingress를 생성 할 수 있게 해주었으며, let’s encrypt 인증서까지 발급이 가능하도록 설정을 해두었습니다.
다음은
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: jekyll-ingress-new
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
ingressClassName: nginx
rules:
- host: blog.montkim.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: jekyll-service
port:
number: 80
tls:
- hosts:
- blog.montkim.com
secretName: jekyll-tls
여기서 일반 ingress와 다른점을 몇가지 짚어드리겠습니다.
우선은 annotation에 cert-manager의 clusterissuer 를 지정해 인증서를 발급받으려고 합니다.
그 정보는 tls로 선언했으며, secret으로 저장되기때문에 해당 도메인과 secret 정보를 기재했습니다.
추가적으로 spec.ingressClassName에 ingress class를 지정해 설치한 ingress nginx controller로 맵핑을 완료한 ingress 파일입니다.
블로그에 접속해도 정상적인 인증서가 발급된것을 보실 수 있습니다.
예시로 제 블로그의 ingress 파일을 예시로 삼았지만, https (ssl/tls)를 사용 해야할 이유는 많습니다. 일부 보안을 중요시 하는 프로그램들은 https로 연결이 되어있지 않으면 연동이 되지 않는 경우도 있습니다.
물론 HTTPS 인증서의 가격은 여러가지의 이해관계가 얽혀있어 책정되는것이지만, https 기능자체가 필요하다면 이런 방법들로 무료 인증서를 사용하기에 적합하다는 생각이 드네요.
오늘은 이렇게 ingress와 구성요소들에 대해서 알아보았습니다.
그럼 20000