Kong Gateway의 커스텀을 통해 구성 복잡도를 낮추어보자

Kubernetes Advanced Networking Study에 참여하여 약 2달여간 열심히 쫓아갔습니다. 마지막 졸업과제로 어떤 주제를 할지 많은 고민을 하다가, 최근 ServiceMesh에 대해 공부도 하면서, 동시에 쓰이지는 못했지만, 진행해보았던 커스터 마이징을 했던 작업에 대해 정리해보고자 합니다. 이 작업의 목표는 Kong Gateway의 복잡도를 낮추고, 특정 namespace에서만 구동되도록 합니다.

1. Kong Gateway의 전반적인 설정 내역을 확인하기 위해 샘플(?) 어플리케이션의 설정을 수집합니다.

복잡도를 낮추는 작업을 하기 위해서는 Kong Gateway 배포시 사용하는 각종 리소스들에 대한 정보를 수집해야합니다. 여기서는 Helm을 통한 배포와 배포 후 나오는 설정값들을 수집합니다.

# kong helm chart 다운로드 및 value.yaml 파일을 수정
git clone https://github.com/Kong/charts.git

# kong namespace 생성
k create ns kong

# kong gateway helm chart의 의존성 패키지 다운로드
helm dependency update

# helm3 를 통한 kong gateway 배포
helm install . --generate-name --set ingressController.installCRDs=false --debug

2. 터미널에 출력되는 데이터를 분석합니다.

앞에서의 kong gateway 배포를 진행하게되면, 아래와 같이 터미널에 데이터가 출력됩니다. 이 출력은 --debug 옵션을 주었을 때만 나오는 것으로 빼먹지 않고 같이 입력하여 배포되는 리소스들의 yaml 내용을 수집합니다.

(🧑‍🎓 |Istio-k8s:default) root@k8s-m:~/charts/charts/kong# helm install . -g -n kong --set ingressController.installCRDs=false --debug
install.go:178: [debug] Original chart version: ""
install.go:195: [debug] CHART PATH: /root/charts/charts/kong

client.go:128: [debug] creating 6 resource(s)
install.go:151: [debug] CRD kongclusterplugins.configuration.konghq.com is already present. Skipping.
client.go:128: [debug] creating 7 resource(s)
NAME: chart-1646575860
LAST DEPLOYED: Sun Mar  6 23:11:00 2022
NAMESPACE: kong
STATUS: deployed
REVISION: 1
USER-SUPPLIED VALUES:
ingressController:
  installCRDs: false

COMPUTED VALUES:
admin:
  annotations: {}
  enabled: false
  http:
    containerPort: 8001
    enabled: false
    parameters: []
    servicePort: 8001
~~~~~~
~~~~~~
      terminationGracePeriodSeconds: 30
      tolerations:
        []
      volumes:
        - name: chart-1646575860-kong-prefix-dir
          emptyDir: {}
        - name: chart-1646575860-kong-tmp
          emptyDir: {}

NOTES:
To connect to Kong, please execute the following commands:

HOST=$(kubectl get svc --namespace kong chart-1646575860-kong-proxy -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
PORT=$(kubectl get svc --namespace kong chart-1646575860-kong-proxy -o jsonpath='{.spec.ports[0].port}')
export PROXY_IP=${HOST}:${PORT}
curl $PROXY_IP

Once installed, please follow along the getting started guide to start using
Kong: https://docs.konghq.com/kubernetes-ingress-controller/latest/guides/getting-started/

3. 분석 및 수정

helm 배포시 --debug 옵션을 추가하게되면, chart의 value.yaml 파일의 설정값을 먼저 표시를하고, 그 다음에 hooks로 value.yaml 값에 따라 설정된 리소스 yaml 파일 내용이 따라옵니다.

위에서 수집한 데이터 중 Hooks 항목을 확인합니다. 그리고 필요가 없다고 판단되는 것들을 골라서 제거합니다.

커스터마이징에 필요한 부분은 다음과 같습니다.

  • ServiceAccount
  • ClusterRole
  • ClusterRoleBinding
  • Role
  • RoleBinding
  • Service
  • Deployment

극단적으로 간소화하는 경우에는 아래 부분만 있어도 됩니다.

  • ServiceAccount
  • Service
  • Deployment

필요한 부분만 추출한 내용은 여기에서 확인가능합니다.

ServiceAccount

ServiceAccount의 이름과, 레이블을 조금 정리합니다.

apiVersion: v1
kind: ServiceAccount
metadata:
  name: kong-gateway
  namespace: default
  labels:
    app.kubernetes.io/name: kong

ClusterRole

동일하게 이름과 레이블을 정리하고, rules에서 간소화하며 필요없는 권한들을 정리합니다.

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  labels:
    app.kubernetes.io/name: kong
  name: kong-gateway
- apiGroups:
  - ""
  resources:
  - services
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - services/status
  verbs:
  - get
  - patch
  - update

ClusterRoleBinding

크게 변경할 것은 없으며, ServiceAccount와 같이 일부 수정합니다.

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: kong-gateway
  labels:
    app.kubernetes.io/name: kong
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: kong-gateway
subjects:
  - kind: ServiceAccount
    name: kong-gateway
    namespace: kong

Role

ClusterRole과 유사하게 필요한 것만 선택하여 수정합니다.

  - apiGroups:
      - ""
    resources:
      - services
      - endpoints
    verbs:
      - get

RoleBinding

이것도 일부 수정해 줍니다.

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: kong-gateway
  namespace: default
  labels:
    app.kubernetes.io/name: kong
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: kong-gateway
subjects:
  - kind: ServiceAccount
    name: kong-gateway
    namespace: default

Service

deployment 수정할 내용에 맞추어 일부 수정합니다.

apiVersion: v1
kind: Service
metadata:
  name: kong-gateway
  namespace: default
  labels:
    app.kubernetes.io/name: kong
spec:
  type: LoadBalancer
  ports:
  - name: kong-proxy
    port: 80
    targetPort: 8000
    appProtocol: http
    protocol: TCP
  - name: kong-proxy-tls
    port: 443
    targetPort: 8443
    appProtocol: https
    protocol: TCP
  selector:
    app.kubernetes.io/name: kong

Deployment

앞서 수정한 내용에 맞추어 수정합니다. 네임스페이스는 default로 맞추어 줍니다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: kong-gateway
  namespace:  default
  labels:
    app.kubernetes.io/name: kong
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: kong
  template:
      labels:
        app.kubernetes.io/name: kong
    spec:
      serviceAccountName: kong-gateway
~~~~~

4. 배포 및 통신 확인

위에서 수정한 yaml 파일들을 쿠버네티스에 배포합니다. 이후에 kong admin api를 참조하여 services와 routes 설정을 하고, 테스트를 진행합니다.

샘플 어플리케이션

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy1-websrv
spec:
  replicas: 1
  selector:
    matchLabels:
      app: websrv
  template:
    metadata:
      labels:
        app: websrv
    spec:
      containers:
      - name: pod-web
        image: nginx
---
apiVersion: v1
kind: Service
metadata:
  name: svc1-web
spec:
  ports:
    - name: web-port
      port: 9001
      targetPort: 80
  selector:
    app: websrv
  type: ClusterIP

테스트 진행

curl -v "http://10.101.125.11:32736/kong-test" -H 'Host: kong.ysyu.kr'

*   Trying 10.101.125.11:32736...
* Connected to 10.101.125.11 (10.101.125.11) port 32736 (#0)
> GET /kong-test HTTP/1.1
> Host: kong.ysyu.kr
> User-Agent: curl/7.74.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: nginx/1.21.6
< Date: Sat, 12 Mar 2022 12:15:48 GMT
< Content-Type: text/html
< Content-Length: 615
< Last-Modified: Tue, 25 Jan 2022 15:03:52 GMT
< Connection: keep-alive
< ETag: "61f01158-267"
< Accept-Ranges: bytes
<
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
* Connection #0 to host 10.101.125.11 left intact

5. 마무리

이번 포스팅과 같이 Kong Gateway 뿐만 아니라, 다른 어플리케이션들도 동일하게 내용을 추출하여 원하는대로 수정할수 있습니다. 특히나, Helm Chart가 제공되는 어플리케이션에 대한 분석을 진행해보면 Kubernetes의 RBAC에 대한 것도 덤으로 공부가 가능합니다.

6. Kubernets Advanced Networking Study를 마무리하며.

8주동안 쿠버네티스 네트워크라는 주제로 재미있게 공부했습니다. 쿠버네티스내의 네트워크 관련하여 모든 구성요소들을 파본것은 아니지만, CNI와 Ingress, ServiceMesh에 대해 작동하는 모습, 흐름에 대한 이해도를 높일수 있었습니다. 스터디에 함께하셨던 분들께도 고생하셨다고 전달하고 싶고, 끝까지 잘 이끌어주셨던 가시다님에게도 감사하다는 말을 전하고 싶습니다.