nginx ingress 마지막 고집: admission webhook

배경
k8s 에 서 는 nginx - ingress - controller 를 사용 하여 ingress 를 실현 하지만 취약 한 nginx - controller 는 ingress 를 통 해 nginx 설정 을 분석 합 니 다. 일부 annotation 에 서 는 reload nignx 설정 이 실 패 했 습 니 다. 그 다음 에 controller 가 끊 겨 서 계속 재 부팅 합 니 다. 해당 하 는 ingress 를 삭제 하지 않 는 한.
문제 가 재현 되다
문제 가 있 는 것 만 들 기 ingress
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/auth-tls-pass-certificate-to-upstream: "false"
    nginx.ingress.kubernetes.io/auth-tls-verify-client: optional
    nginx.ingress.kubernetes.io/auth-tls-verify-depth: "1"
    nginx.ingress.kubernetes.io/configuration-snippet: |
      proxy_set_header Host $targethost;
      proxy_buffering     off;
      proxy_pass          http://$targetbackend;
      proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
      proxy_redirect      off;
      proxy_set_header    X-SSL-Client-Verify $ssl_client_verify;
      proxy_set_header    X-SSL-Client-DN $ssl_client_s_dn;
      proxy_set_header    X-Real-IP       $remote_addr;
      proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;
  creationTimestamp: "2020-03-23T04:57:22Z"
  generation: 1
  name: example-ingress
  namespace: kube-system
  resourceVersion: "57681168"
  selfLink: /apis/extensions/v1beta1/namespaces/kube-system/ingresses/example-ingress
  uid: c7f66385-6cc2-11ea-b6a8-246e96d4b538
spec:
  rules:
  - host: example.com
    http:
      paths:
      - backend:
          serviceName: example-svc
          servicePort: 8008
        path: /
  tls:
  - hosts:
    - example.com
    secretName: example-tls
status:
  loadBalancer: {}

보기 nginx-ingress-controller 상태 모두 CrashLoopBackOff
# kubectl get po -n kube-system -owide |grep ingress
nginx-ingress-controller-ftfbg                        1/2     CrashLoopBackOff   6          8m27s
nginx-ingress-controller-hp4pf                        1/2     CrashLoopBackOff   11         24m  
nginx-ingress-controller-qlb4l                        1/2     CrashLoopBackOff   11         24m   

로그 보기 nginx-ingress-controller, reload 실패 표시 "proxy_pass" directive is duplicate in /tmp/nginx-cfg911768424:822
-------------------------------------------------------------------------------
W0403 10:26:14.716246       1 queue.go:130] requeuing kube-system/nginx-ingress-controller-4txfk, err 
-------------------------------------------------------------------------------
Error: exit status 1
2020/04/03 10:26:14 [notice] 137#137: ModSecurity-nginx v1.0.0
2020/04/03 10:26:14 [warn] 137#137: duplicate value "error" in /tmp/nginx-cfg911768424:815
nginx: [warn] duplicate value "error" in /tmp/nginx-cfg911768424:815
2020/04/03 10:26:14 [warn] 137#137: duplicate value "timeout" in /tmp/nginx-cfg911768424:815
nginx: [warn] duplicate value "timeout" in /tmp/nginx-cfg911768424:815
2020/04/03 10:26:14 [emerg] 137#137: "proxy_pass" directive is duplicate in /tmp/nginx-cfg911768424:822
nginx: [emerg] "proxy_pass" directive is duplicate in /tmp/nginx-cfg911768424:822
nginx: configuration file /tmp/nginx-cfg911768424 test failed

-------------------------------------------------------------------------------
W0403 10:26:16.998897       1 nginx_status.go:207] unexpected error obtaining nginx status info: unexpected error scraping nginx status page: unexpected error scraping nginx : Get http://0.0.0.0:18080/nginx_status: dial tcp 0.0.0.0:18080: connect: connection refused
I0403 10:26:17.526801       1 main.go:167] Received SIGTERM, shutting down
I0403 10:26:17.526827       1 nginx.go:364] Shutting down controller queues
I0403 10:26:17.526845       1 status.go:200] updating status of Ingress rules (remove)
I0403 10:26:17.537511       1 status.go:219] removing address from ingress status ([])
I0403 10:26:17.537593       1 nginx.go:372] Stopping NGINX process
2020/04/03 10:26:17 [notice] 141#141: signal process started
I0403 10:26:20.547669       1 nginx.go:385] NGINX process has stopped
I0403 10:26:20.547692       1 main.go:175] Handled quit, awaiting Pod deletion
I0403 10:26:30.547824       1 main.go:178] Exiting with 0

해결 방안
문제 가 있 는 ingress 를 만 들 면 새로 만 든 ingress 규칙 에 영향 을 주 고 또 하나의 클 러 스 터 등급 의 bug 가 탄생 합 니 다. 그러면 방법 이 있 습 니까? ingress 설정 을 미리 검사 하고 문제 가 있 으 면 reload 하지 않 습 니 다. 그 검증 절 차 는 nginx - contrller 에 도착 하 라 고 요청 해 야 합 니 다. k8s - admission - webhook 을 생각 했 습 니까? apiserver 의 지속 적 인 대상 앞에서 요청 을 차단 할 수 있 습 니 다.사용자 정의 인증 규칙 을 실현 합 니 다. 자, 새 버 전의 nginx - ingress - controller (v 0.25.0 +) 에서 관련 기능 을 실 현 했 습 니 다. 해당 설정 만 켜 면 됩 니 다.
ApiServer 설정
Apiserver 에서 webhook 관련 설정 을 열 려 면 MutatingAdmissionWebhookValidatingAdmissionWebhook 를 포함해 야 합 니 다.
--admission-control=MutatingAdmissionWebhook,ValidatingAdmissionWebhook

웹 훅 관련 설정 만 들 기
ValidatingAdmissionWebhook 을 사용 하려 면 https 를 사용 해 야 합 니 다. 해당 인증 서 를 설정 해 야 합 니 다.
  • 수 동 생 성:
    openssl req -x509 -newkey rsa:2048 -keyout certificate.pem -out key.pem -days 365 -nodes -subj "/CN=ingress-validation-webhook.ingress-nginx.svc"
    
  • Certificate Signing Request 는 k8s CertificateSigningRequest 를 통 해 만 들 수 있 습 니 다 (controller - manager 가 켜 야 합 니 다 --cluster-signing-cert-file--cluster-signing-key-file 다음 스 크 립 트 를 통 해 만 들 수 있 습 니 다. namespace 와 service 는 자신의
    SERVICE_NAME=ingress-nginx
    NAMESPACE=ingress-nginx
    
    TEMP_DIRECTORY=$(mktemp -d)
    echo "creating certs in directory ${TEMP_DIRECTORY}"
    
    cat <<EOF >> ${TEMP_DIRECTORY}/csr.conf
    [req]
    req_extensions = v3_req
    distinguished_name = req_distinguished_name
    [req_distinguished_name]
    [ v3_req ]
    basicConstraints = CA:FALSE
    keyUsage = nonRepudiation, digitalSignature, keyEncipherment
    extendedKeyUsage = serverAuth
    subjectAltName = @alt_names
    [alt_names]
    DNS.1 = ${SERVICE_NAME}
    DNS.2 = ${SERVICE_NAME}.${NAMESPACE}
    DNS.3 = ${SERVICE_NAME}.${NAMESPACE}.svc
    EOF
    
    openssl genrsa -out ${TEMP_DIRECTORY}/server-key.pem 2048
    openssl req -new -key ${TEMP_DIRECTORY}/server-key.pem \
        -subj "/CN=${SERVICE_NAME}.${NAMESPACE}.svc" \
        -out ${TEMP_DIRECTORY}/server.csr \
        -config ${TEMP_DIRECTORY}/csr.conf
    
    cat <<EOF | kubectl create -f -
    apiVersion: certificates.k8s.io/v1beta1
    kind: CertificateSigningRequest
    metadata:
      name: ${SERVICE_NAME}.${NAMESPACE}.svc
    spec:
      request: $(cat ${TEMP_DIRECTORY}/server.csr | base64 | tr -d '
    '
    )
    usages: - digital signature - key encipherment - server auth EOF kubectl certificate approve ${SERVICE_NAME}.${NAMESPACE}.svc for x in $(seq 10); do SERVER_CERT=$(kubectl get csr ${SERVICE_NAME}.${NAMESPACE}.svc -o jsonpath='{.status.certificate}') if [[ ${SERVER_CERT} != '' ]]; then break fi sleep 1 done if [[ ${SERVER_CERT} == '' ]]; then echo "ERROR: After approving csr ${SERVICE_NAME}.${NAMESPACE}.svc, the signed certificate did not appear on the resource. Giving up after 10 attempts." >&2 exit 1 fi echo ${SERVER_CERT} | openssl base64 -d -A -out ${TEMP_DIRECTORY}/server-cert.pem kubectl create secret generic ingress-nginx.svc \ --from-file=key.pem=${TEMP_DIRECTORY}/server-key.pem \ --from-file=cert.pem=${TEMP_DIRECTORY}/server-cert.pem \ -n ${NAMESPACE}
  • 로 바 꿀 수 있 습 니 다.
    ingress 컨트롤 러 설정
    ingress contrller 는 다음 매개 변 수 를 사용 해 야 합 니 다. 필요 한 tles 인증 서 를 마 운 트 해 야 합 니 다.
    flag
    description
    example usage --validating-webhook
    admission webhook 주소:8080 --validating-webhook-certificate
    웹 훅 인증서/usr/local/certificates/validating-webhook.pem --validating-webhook-key
    웹 훅 비밀 키/usr/local/certificates/validating-webhook-key.pem
    검증 하 다.
    업데이트 후 문제 가 있 는 ingress 를 만 들 면 차단 되 어 예상 에 부합 합 니 다.
    # kubectl apply -f ing.yaml
    Error from server: error when creating "ing.yaml": admission webhook "validate.nginx.ingress.kubernetes.io" denied the request: 
    -------------------------------------------------------------------------------
    Error: exit status 1
    2020/04/02 10:26:04 [emerg] 331#331: directive "proxy_pass" is not terminated by ";" in /tmp/nginx-cfg461116913:2165
    nginx: [emerg] directive "proxy_pass" is not terminated by ";" in /tmp/nginx-cfg461116913:2165
    nginx: configuration file /tmp/nginx-cfg461116913 test failed
    

    인용 하 다.
  • https://kubernetes.io/zh/docs/reference/access-authn-authz/extensible-admission-controllers/
  • https://kubernetes.github.io/ingress-nginx/deploy/validating-webhook/
  • https://qingwave.github.io/ingress-nginx-controller-admission-webhook/

  • Qinng 's Blog

    좋은 웹페이지 즐겨찾기