Webサイトにアクセスできない

概要

サーバーを勉強するためにおうちラックを買った先輩がKubernetesに手を出し始めたらしい。
Ingressを使って Webサイトを用意したところ、なぜかつながらないらしい。
原因を究明してつながるようにしてほしい。

前提条件

  • Ingressはnginx.ingress.kubernetes.io/proxy-bufferingをonにしたまま
  • はじめにデプロイされていたリソースを削除しない
  • デプロイされているPodを変更してはいけない

初期状態

  • 問題環境に接続するためのbastionサーバーから curl -k https://192.168.13.101 をすると、502が返ってくる 。

終了状態

手元のPCから curl -k https://192.168.13.101 をするとステータスコード200の以下のレスポンスが返ってくる。

welcome to ictsc2021 summer

解説

KubernetesのNginx Ingress に関する問題でした。

問題の初期状態

  • Kubeadmによって構築されたK8sクラスタにMetalLB、Nginx ingress Controller、Nginxがデプロイされている。
  • MetalLBはサンプル通り、[Nginx ingress Controller](https://kubernetes.github.io/ingress-nginx/deploy/#bare-metalはServiceをNodePortからLoadBalancerに変更したもの
  • そのほかのマニフェスト,利用したファイルは以下
    ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/proxy-buffering: "on"
    nginx.ingress.kubernetes.io/proxy-buffer-size: "8"
    kubernetes.io/ingress.allow-http: "false"
  name: nginx-ingress
spec:
  tls:
  - secretName: tls-secret
  rules:
  - http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginx-svc
            port:
              number:  443

nginx.yaml

---
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
  labels:
    app: nginx
spec:
  selector:
    app: nginx
  ports:
  - name: https
    protocol: TCP
    port: 443
    targetPort: 443
  - name: http
    protocol: TCP
    port: 80
    targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 443
        - containerPort: 80
        volumeMounts:
        - name: nginx-conf
          mountPath: /etc/nginx/conf.d
        - name: tls-cert
          mountPath: /etc/nginx/tls
        - name: index-html
          mountPath: /usr/share/nginx/html
      volumes:
      - name: nginx-conf
        configMap:
          name: nginx-conf
      - name: tls-cert
        secret:
          secretName: tls-secret
      - name: index-html
        configMap:
          name: index-html

index.html

welcome to ictsc2021 summer
  • curl -k https://192.168.13.101を問題環境に接続するための踏み台や K8sクラスタのVMから行うと、502 Bad Gatewayが返ってくる。

解答解説

ingress.yamlでnginx.ingress.kubernetes.io/proxy-buffer-size: "8"と指定されており、バックエンドからプロキシが受け取ることができるヘッダーサイズがとても小さくなっている。
また、Ingressがバックエンドの443番ポートにアクセスしているが、Nginx ingress controllerはデフォルトでHTTPを使うため、プロトコルの違いによってコンテンツが取得できない。

  • nginx.ingress.kubernetes.io/proxy-buffer-size が “8” から”256″や”8k”などコンテンツを配信できるバッファサイズに変更
  • nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"をannotationに追加
    することで解決できる。

その他

割と、PodのSVCに直接指定したIPアドレスを割り当てる解答がありましたが、Ingressを使う旨が問題文にあったので終了条件は満たしていますが減点しました。
また、Pod/PodのSVCは80で受け付けているので、backend-protocol アノテーションをつけなくても解答できることに今気づきました。