OpenShift v4.x – Custom Router 설정
OpenShift에서 사용되는 Ingress Controller는 Router Pod를 사용한다.
HAProxy 기반에 go template을 사용하여 자동화 되어있다.

고객사 환경마다 각기 다른 요구사항들이 존재하기 때문에,
RedHat에서 제공하지 않는 HAProxy의 세부 옵션들을 사용할 경우
사용자 정의 형태로 haproxy template를 수정하여 옵션을 사용해야 한다.

고객사 이슈 중 하나는 외부 사용자가 한글이 포함 된 Query String를 호출을 하는 경우에 발생했는데,
HAProxy 단에서 400 bad request를 출력 하는 문제가 있었다.

이 이슈는 RFC7230에서 URI 특수문자를 허용하지 않아 발생하는 문제였다.

이를 해결하는 방법은 HAProxy에서 ‘option accept-invalid-http-request’, ‘option accept-invalid-http-response’ 두가지 옵션을
추가하는 방법으로 해결이 되지만, 보안상 운영 환경에서 이 옵션을 사용하지 않는 것이 좋다고 한다.

위 두가지 옵션을 haproxy template에 변수로 추가하여 추가하는 방법에 대해서 작성한다.

1. 리소스 백업
기존의 ingress operator에서 생성 한 Router Pod의 Deploymet를 yaml 파일로 백업 한다.

– Deployment 백업
[root@bastion ~]# oc get deployment.apps/router-default -n openshift-ingress \
-o yaml > router-custom-deployment.yaml

2. HAProxy Template 작업
HAProxy의 템플릿을 수정하려면 구동 중인 Router Pod의 아래 경로에서 파일이 필요하므로 복사 해온다.

– Router Pod 확인
[root@bastion ~]# oc project openshift-ingress
[root@bastion ~]# oc get pod
NAME READY STATUS RESTARTS AGE
router-default-68dc5584d6-qgsrm 1/1 Running 0 1h

– template 복사
Router Pod에 존재하는 haproxy-config.template 파일을 현재 경로에 복사 한다.
[root@bastion ~]# oc rsync router-default-68dc5584d6-qgsrm:/var/lib/haproxy/conf/haproxy-config.template ./

– template 수정
해당 옵션을 관련 링크 [1]~[7]을 참고하여 각각의 위치에 맞게 추가 한다.
accept-invalid-http-request는 frontend 부분, accept-invalid-http-response는 backend 부분에만 설정 했다.

* custom variable
[1]: https://gist.github.com/ruo91/5b12d82d5a6c8edbc1c4f00e010527dd#file-ocp4-custom-router-haproxy-config-template-L13-L15

* accept-invalid-http-request
[2]: https://gist.github.com/ruo91/5b12d82d5a6c8edbc1c4f00e010527dd#file-ocp4-custom-router-haproxy-config-template-L201-L204
[3]: https://gist.github.com/ruo91/5b12d82d5a6c8edbc1c4f00e010527dd#file-ocp4-custom-router-haproxy-config-template-L240-L243
[4]: https://gist.github.com/ruo91/5b12d82d5a6c8edbc1c4f00e010527dd#file-ocp4-custom-router-haproxy-config-template-L299-L302
[5]: https://gist.github.com/ruo91/5b12d82d5a6c8edbc1c4f00e010527dd#file-ocp4-custom-router-haproxy-config-template-L390-L393

* accept-invalid-http-response
[6]: https://gist.github.com/ruo91/5b12d82d5a6c8edbc1c4f00e010527dd#file-ocp4-custom-router-haproxy-config-template-L459-L462
[7]: https://gist.github.com/ruo91/5b12d82d5a6c8edbc1c4f00e010527dd#file-ocp4-custom-router-haproxy-config-template-L489-L492

3. Ingress Operator 비활성화
ingress controller인 Router Pod는 ingress-operator라는 Pod에 의해 Deployment, ReplicaSet등의 리소스를 자동 감시/관리 한다.
그래서, ingress operator를 비활성화 해야 custom template을 적용하여 반영할 수 있기 때문에 해당 작업을 진행한다.

– ingress operator 비활성화
replicas 개수를 0으로 변경하여 비활성화 한다.
[root@bastion ~]# oc patch ingresscontrollers.operator.openshift.io/default \
–namespace openshift-ingress-operator –type=merge –patch ‘{“spec”: {“replicas”: 0}}’

4. Deployment 수정 및 배포
기존의 ingress-operator가 생성한 deployment의 이름을 중복적으로 사용할 수 없기 때문에 이름을 변경한다.
[root@bastion ~]# sed -i ‘/^router-default/ s:.*:router-custom-20210210:’ router-custom-deployment.yaml

replicas 개수도 사용할 만큼 수정한다.
[root@bastion ~]# sed -i ‘/^replicas/ s:.*:replicas\: 1:’ router-custom-deployment.yaml

Router Pod를 배포한다.
[root@bastion ~]# oc create -f router-custom-deployment.yaml -n openshift-ingress

Router Pod 상태를 확인한다.
[root@bastion test]# oc get pod -n openshift-ingress
NAME READY STATUS RESTARTS AGE
router-custom-20210210-668cfb8855-qbcmc 1/1 Running 0 24s

5. Configmap 생성
2번에서 수정한 template 파일을 configmap을 통해 저장한다.
[root@bastion ~]# oc create configmap haproxy-custom-20210210 \
–from-file=haproxy-config.template -n openshift-ingress

6. Volume Mount
template 파일이 저장 된 configmap을 Router Pod에 강제 마운트 한다.
[root@bastion ~]# oc set volume deployment.apps/router-custom-20210210 \
–add –overwrite –name=config-volume \
–mount-path=/var/lib/haproxy/conf/custom \
–source='{“configMap”: { “name”: “haproxy-custom-20210210”}}’

7. Template 위치 변경
deployment의 변수에 custom template를 사용하도록 위치를 변경한다.
[root@bastion ~]# oc set env deployment.apps/router-custom-20210210 TEMPLATE_FILE=/var/lib/haproxy/conf/custom/haproxy-config.template

8. 변수 등록
2번에서 등록한 custom 변수를 deployment에 추가한다.
[root@bastion ~]# oc set env deployment.apps/router-custom-20210210 ROUTER_ENABLE_HTTP_REQUEST=true
[root@bastion ~]# oc set env deployment.apps/router-custom-20210210 ROUTER_ENABLE_HTTP_RESPONSE=true

– RefURL
* Example – Router Deployment
[8]: https://gist.github.com/ruo91/72ddbbbd47d97d7d05d8f8b67ec31579

9. 확인
custom 변수가 잘 반영이 되었는지 Router Pod에서 해당 옵션을 확인 한다.
– Router Pod 확인
[root@bastion ~]# oc get pod
NAME READY STATUS RESTARTS AGE
router-custom-20210210-5d9586fb89-zfsk6 1/1 Running 0 2m5s

– HAProxy 옵션 확인
[root@bastion ~]# oc rsh router-custom-20210210-5d9586fb89-zfsk6 grep -R ‘accept-invalid-http’ /var/lib/haproxy/conf/haproxy.config
option accept-invalid-http-request
option accept-invalid-http-request
option accept-invalid-http-request
option accept-invalid-http-request
option accept-invalid-http-response
option accept-invalid-http-response
option accept-invalid-http-response
option accept-invalid-http-response
option accept-invalid-http-response
option accept-invalid-http-response
option accept-invalid-http-response
option accept-invalid-http-response
option accept-invalid-http-response
option accept-invalid-http-response