Ingress에 대해서 - kuberetes ingress controller for kong & istio

양승현·2023년 7월 22일
2

OpenSource

목록 보기
6/7


kong이란

  • Kong 공식페이지를 보면, Kong은 MSA구성을 가속화하는 가장 유명한 오픈 소스 API Gateway라고 말한다.
  • 또한 경량화 된 프록시 환경위에 구축 되어 있어, 어디서든지 모든 마이크로 서비스에 성능 및 확장성을 제공한다.
  • 이외에도 가장 큰 특징은, 모든 기능을 Restful Interface로 제공하고 있으며, API Gateway를 구성하는 필수 기능( OAuth 인증, Logging, 유량제어 등)들을 Plugin 기반으로 손쉽게 추가하여 사용할 수 있으며, Platform(런타임)에 구애받지 않고 어디서든지 Kong을 구축할 수 있다.
  • kong ingress controller는 kubernetes cluster로 들어오는 트래픽을 프록시하는 것 이상을 수행한다.
  • Controller Manager는 kubernetes cluster 내에서 발생하는 변경 사항을 보고 모든 트래픽을 프록시하기 위해 변경 사항에 대응하여 kong을 업데이트한다.
  • kong은 kubernetes cluster 내에서 발생하는 확장, 구성 변경, 오류에 대한 변경 사항에 대응하기 위해 동적으로 업데이트됩니다.
  • kong은 두 가지 타입으로 설치할 수 있는데, With a Database 와 DB-less Mode가 있다.
  • 여기서는 kong ingress controller 사용에 대해 알아보겠습니다.

실습

spec

- Red Hat Enterprise Linux8
- k8s 1.27.11
- istio 1.17.1
- kong 2.9

istio로 kong ingress 컨트롤로 실행하기

istio 설치

  • istio 1.17.1 version download
curl -s -L https://istio.io/downloadIstio | ISTIO_VERSION=1.17.1 sh -
  • istioctl 추가
export PATH="$PATH:$PWD/istio-1.17.1/bin"
  • 정상 작동 확인
istioctl x precheck
  • service mesh sample app - bookinfo apply
# namespace create
$ kubectl create namespace bookinfo

# istio sidecar enabled in namespace
$ kubectl label namespace bookinfo istio-injection=enabled

# istio sample app - bookinfo apply
$ kubectl -n bookinfo apply -f istio-1.17.1/samples/bookinfo/platform/kube/bookinfo.yaml

# 이후 사이드카 주입 확인 - container 2/2 확인(1/1 상태면 파드 delete 후 apply)
$ kubectl get pod -n bookinfo
NAME                              READY   STATUS    RESTARTS   AGE
details-v1-c5b5f496d-9wm29        2/2     Running   0          101s
productpage-v1-7d6cfb7dfd-5mc96   2/2     Running   0          100s
ratings-v1-f745cf57b-hmkwf        2/2     Running   0          101s
reviews-v1-85c474d9b8-kqcpt       2/2     Running   0          101s
reviews-v2-ccffdd984-9jnsj        2/2     Running   0          101s
reviews-v3-98dc67b68-nzw97        2/2     Running   0          101s

- API 게이트웨이(Kong)와 서비스 메쉬(Istio) 모두 로드 밸런싱을 처리할 수 있는데, ingress.kubernetes.io/service-upstream: "true" 주석이 없으면 Kong은 productpage 서비스에서 자체 엔드포인트/대상을 선택하여 부하 분산을 시도한다.
- 이로 인해 Envoy는 서비스의 클러스터 IP 대신 해당 포드의 IP를 업스트림 로컬 주소로 수신한다.
- 하지만 Envoy가 적절하게 부하를 분산할 수 있도록 서비스의 클러스터 IP가 필요하다.
$ kubectl annotate service productpage ingress.kubernetes.io/service-upstream=true
- 제품 페이지 접근 확인
$ kubectl exec -it $(kubectl get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}') -c ratings -- curl productpage:9080/productpage | grep -o "<title>.*</title>"

k8s - kong 설치(DBless mode)

  • istio 지원 namespace 생성
kubectl create ns kong-istio
  • istio mesh namespace 활성화
kubectl label ns kong-istio istio-injection=enabled
  • kong helm repo 구성
helm repo add kong https://charts.konghq.com && helm repo update
  • chart 배포
helm install -n kong-istio kong-istio kong/kong
  • Kong 컨테이너가 배치되고 Istio 사이드카 컨테이너가 제대로 주입되었는지 확인
kubectl describe pod -n kong-istio -l app.kubernetes.io/instance=kong-istio
  • kong gateway를 통해 외부에 bookinfo 노출
# ingress yaml 생성 후 배포
vi bookinfo-ingress.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: productpage
  namespace: bookinfo
spec:
  ingressClassName: kong
  rules:
  - http:
      paths:
      - path: /
        pathType: ImplementationSpecific
        backend:
          service:
            name: productpage
            port:
              number: 9080

kubectl apply -f bookinfo-ingress.yaml
  • kong gateway를 통해 port 80과 매핑되어 있는 노드포트 확인
kubectl get svc -n kong-istio
  • 요청
watch -n 1 curl IP:nodeport(kong gateway svc)

k8s - kong 설치(DB mode)

  • istio 지원 namespace 생성
kubectl create ns kong
  • istio mesh namespace 활성화
kubectl label ns kong istio-injection=enabled
  • kong helm repo 구성
helm repo add kong https://charts.konghq.com && helm repo update
  • values.yaml 커스터마이징(Postgres subcharts 설치)
vi values.yaml
---
deployment:
  kong:
    enabled: true
  serviceAccount:
    create: true

env:
  nginx_worker_processes: "2"
  anonymous_reports: "off"
  database: "postgres" 

admin:
  enabled: true
  type: NodePort
  annotations: {}

  http:
    enabled: true

  tls:
    enabled: true
    parameters: []

proxy:
  enabled: true
  type: LoadBalancer

  labels:
    enable-metrics: "true"

  http:
    enabled: true
    parameters: []

  tls:
    enabled: true
    parameters: []
   
ingressController:
  enabled: true

  args: 
  - --anonymous-reports=false

  admissionWebhook:
    enabled: false

  ingressClass: kong
  ingressClassAnnotations: {}

  rbac:
    create: true

postgresql:
  enabled: true
  • chart 배포
# istio와 kong의 버전 호환성이 맞지 않으면 kong은 error 상태이다.
helm install kong kong/kong --version 2.9 -n kong -f values.yaml
  • container 확인
k describe deployment.apps/kong-kong -n kong
NAME                                  READY   STATUS      RESTARTS        AGE
pod/kong-kong-6b9cd4d94d-qszqk        3/3     Running     2 (4m30s ago)   5m9s
# 해당 pod의 container는 아래에 해당한다.
	- 1. proxy: 모든 트래픽을 처리하는 핵심 프록시
	- 2. ingress-controller: Kubernetes에서 Kong으로 구성을 동기화하는 일련의 프로세스
    - 3. istio-sidecar container
  • Kong 컨테이너가 배치되고 Istio 사이드카 컨테이너가 제대로 주입되었는지 확인
kubectl describe pod -n kong -l app.kubernetes.io/instance=kong
  • kong gateway를 통해 외부에 bookinfo 노출
# ingress yaml 생성 후 배포
vi bookinfo-ingress.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: productpage
  namespace: bookinfo
spec:
  ingressClassName: kong
  rules:
  - http:
      paths:
      - path: /
        pathType: ImplementationSpecific
        backend:
          service:
            name: productpage
            port:
              number: 9080

kubectl apply -f bookinfo-ingress.yaml
  • kong gateway를 통해 port 80과 매핑되어 있는 노드포트 확인
kubectl get svc -n kong
  • 요청
watch -n 1 curl IP:nodeport(kong gateway svc)

konga 사용하기

  • Konga는 kong-admin을 이용해서 연결되기 때문에 kong-admin service를 생성해준다.
  • kong-admin을 설치하면 나중에 api를 보낼 때 Kong 리소스를 설치할 때 yml파일을 생성하지 않고도 생성할 수 있다.

kong-admin 생성

  • kong-admin 설치
$ kubectl apply -f https://bit.ly/k8s-kong-admin -n kong

or

$ vi kong-admin.yaml

apiVersion: v1
kind: Service
metadata:
  name: kong-admin
spec:
  type: NodePort
  ports:
  - name: admin
    port: 8001
    protocol: TCP
    targetPort: 8001
  - name: admin-ssl
    port: 8444
    targetPort: 8444
    protocol: TCP
  selector:
    app: ingress-kong
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: ingress-kong
  name: ingress-kong
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ingress-kong
  template:
    metadata:
      annotations:
        kuma.io/gateway: enabled
        traffic.sidecar.istio.io/includeInboundPorts: ""
      labels:
        app: ingress-kong
    spec:
      containers:
      - env:
        - name: KONG_DATABASE
          value: postgres
        - name: KONG_PG_HOST
          value: postgres
        - name: KONG_PG_PASSWORD
          value: kong
        - name: KONG_PROXY_LISTEN
          value: 0.0.0.0:8000, 0.0.0.0:8443 ssl http2
        - name: KONG_PORT_MAPS
          value: 80:8000, 443:8443
        - name: KONG_ADMIN_LISTEN
          value: 0.0.0.0:8001, 0.0.0.0:8444 ssl
        - name: KONG_STATUS_LISTEN
          value: 0.0.0.0:8100
        - name: KONG_NGINX_WORKER_PROCESSES
          value: "2"
        - name: KONG_ADMIN_ACCESS_LOG
          value: /dev/stdout
        - name: KONG_ADMIN_ERROR_LOG
          value: /dev/stderr
        - name: KONG_PROXY_ERROR_LOG
          value: /dev/stderr
        image: kong:2.5
        lifecycle:
          preStop:
            exec:
              command:
              - /bin/sh
              - -c
              - kong quit
        livenessProbe:
          failureThreshold: 3
          httpGet:
            path: /status
            port: 8100
            scheme: HTTP
          initialDelaySeconds: 5
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 1
        name: proxy
        ports:
        - containerPort: 8001
          name: admin
          protocol: TCP
        - containerPort: 8444
          name: admin-ssl
          protocol: TCP
        - containerPort: 8000
          name: proxy
          protocol: TCP
        - containerPort: 8443
          name: proxy-ssl
          protocol: TCP
        - containerPort: 8100
          name: metrics
          protocol: TCP
        readinessProbe:
          failureThreshold: 3
          httpGet:
            path: /status
            port: 8100
            scheme: HTTP
          initialDelaySeconds: 5
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 1
      - env:
        - name: CONTROLLER_KONG_ADMIN_URL
          value: https://127.0.0.1:8444
        - name: CONTROLLER_KONG_ADMIN_TLS_SKIP_VERIFY
          value: "true"
        - name: CONTROLLER_PUBLISH_SERVICE
          value: kong/kong-proxy
        - name: POD_NAME
          valueFrom:
            fieldRef:
              apiVersion: v1
              fieldPath: metadata.name
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              apiVersion: v1
              fieldPath: metadata.namespace
        image: kong/kubernetes-ingress-controller:2.0.5
        imagePullPolicy: IfNotPresent
        livenessProbe:
          failureThreshold: 3
          httpGet:
            path: /healthz
            port: 10254
            scheme: HTTP
          initialDelaySeconds: 5
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 1
        name: ingress-controller
        ports:
        - containerPort: 8080
          name: webhook
          protocol: TCP
        - containerPort: 10255
          name: cmetrics
          protocol: TCP
        readinessProbe:
          failureThreshold: 3
          httpGet:
            path: /readyz
            port: 10254
            scheme: HTTP
          initialDelaySeconds: 5
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 1
      initContainers:
      - command:
        - /bin/sh
        - -c
        - while true; do kong migrations list; if [[ 0 -eq $? ]]; then exit 0; fi;
          sleep 2;  done;
        env:
        - name: KONG_PG_HOST
          value: postgres
        - name: KONG_PG_PASSWORD
          value: kong
        image: kong:2.9
        name: wait-for-migrations
      serviceAccountName: kong-serviceaccount

$ kubectl apply -f kong-admin.yaml -n kong-istio
  • kong-admin 설치 확인
# kong-admin 설치 확인
kubectl get svc -n kong kong-admin
service/kong-kong-admin      NodePort       10.96.15.131   <none>        8001:32080/TCP,8444:31448/TCP   14h

konga service 및 deployment 생성

  • konga-service 및 deployment 생성
$ kubectl create -f https://bit.ly/k8s-konga -n kong

or
$ vi konga.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: konga
spec:
  replicas: 1
  selector:
      matchLabels:
        app: konga
        name: konga
  template:
    metadata:
      labels:
        name: konga
        app: konga
    spec:
      containers:
      - name: konga
        image: pantsel/konga
        ports:
        - containerPort: 1337
        env:
          - name: NO_AUTH
            value: "true"
---
apiVersion: v1
kind: Service
metadata:
  name: konga-svc
spec:
  type: NodePort
  ports:
  - name: kong-proxy
    port: 1337
    targetPort: 1337
    nodePort: 30331
    protocol: TCP
  selector:
    app: konga

$ kubectl apply -f konga.ayml -n kong-istio
  • konga-service 및 deployment 설치 확인
kubectl get svc -n kong konga-svc
konga-svc            NodePort       10.96.5.131    <none>        1337:30330/TCP                  3m19s

접속

# konga-svc nodeport
192.168.60.240:30330

  • 접속 정보
Name
kong

# kong-admin nodeport
Kong Admin URL
http://192.168.60.240:32080


  • kong은 DB mode와 DBless mode 두가지 모드를 지원한다.
  • DBless mode에서는 지원 안 하는 Plugin이 있어 DB mode를 사용하는 게 좋다.
  • 다양한 Plugin이 존재하는데 상황에 따라 Global, Service, Route 단위로 설정할 수 있다.
  • Admin API에 curl 요청을 보내 Service, Route, Plugin을 설정하거나 K8S Resource Service, Ingress, KongPlugin를 통해 설정할 수 있다.

참고 자료

- monitoring tool - kiali, prometheus, grafana 등 시각화 툴 설치 방법은 아래 공식 문서에 나와 있습니다.

주의 - 학습 목적으로 정리하여 개인적인 견해와 내용이 포함되어 있어 틀린 부분이 많을 수 있습니다.

2개의 댓글

comment-user-thumbnail
2023년 7월 22일

이런 유용한 정보를 나눠주셔서 감사합니다.

답글 달기
comment-user-thumbnail
2023년 7월 24일

좋은 정보 감사합니다!

답글 달기