IBM Cloud Private (ICP) のIngress用Default Backendを変更する

# 目的

ICP(IBM Cloud Private)はクラスタ外部からの通信用に標準でIngressがデプロイされています。Ingressはバックエンドのサービスにマッピングされていないリクエストがきたときに、Default Backendというサービスを呼ぶようになっていますが、その結果は、

![image.png](https://qiita-image-store.s3.amazonaws.com/0/241424/5b83413c-a5f0-8dd9-9adf-2b69a838a191.png)

と出力されるだけの簡素なものです。実運用を考えるともう少しリッチなコンテンツを返したいところですので、Default BackendをNginxに変更してみます。

検証環境
- IBM Cloud Private (ICP) 2.1.0.1 (Kubernetes 1.8)

# 手順

## コンテンツファイルの作成

404応答用の404.htmlと200応答用のhealthz.htmlを用意します。

```404.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>404 Not Found</title>
</head>
<body>
<!-- お好きに -->
<h1>お探しのコンテンツはありません</h1>
</body>
</html>
```

```healthz.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>200 Status Up</title>
</head>
<body>
<!-- 何でもいい -->
up
</body>
</html>
```

## nginx設定ファイルの作成

nginxのconf.d/default.confを上書きするdefault.confを用意します。

```default.conf
server {
    listen       80;

    root         /usr/share/nginx/html;
    error_page   404 /404.html;

    location / {
        return   404;
    }

    location /404.html {
        internal;
    }

    location /healthz {
        alias    /usr/share/nginx/html/healthz.html;
    }
}
```

## イメージのビルド

Dockerfileです。

```Docker:Dockerfile
FROM nginx:1.13.9
RUN rm /usr/share/nginx/html/*
ADD 404.html /usr/share/nginx/html/
ADD healthz.html /usr/share/nginx/html/
ADD default.conf /etc/nginx/conf.d/
```

イメージをビルドしてプライベートレジストリに登録します。namespaceはdefaultを使用しています。

```
docker build -t custom-defaultbackend .
docker tag custom-defaultbackend mycluster.icp:8500/default/custom-defaultbackend:1.0.0
docker push mycluster.icp:8500/default/custom-defaultbackend:1.0.0
```

## デプロイ

Serviceとしてデプロイするための定義です。

```deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: custom-default-http-backend
  namespace: default
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: custom-default-http-backend
    spec:
      containers:
      - image: mycluster.icp:8500/default/custom-defaultbackend:1.0.0
        livenessProbe:
          httpGet:
            path: /healthz
            port: 80
            scheme: HTTP
        name: custom-default-http-backend
        ports:
        - containerPort: 80
          protocol: TCP
```

```service.yaml
apiVersion: v1
kind: Service
metadata:
  name: custom-default-http-backend
  namespace: default
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: custom-default-http-backend
```

これでデプロイします。

```
kubectl apply -f deployment.yaml service.yaml
```

## Ingressの変更

最後にIngressから参照するサービスを変更します。

```
kubectl edit daemonSet nginx-ingress-lb-amd64 -n kube-system

        - --default-backend-service=$(POD_NAMESPACE)/default-http-backend
        を以下に変更
        - --default-backend-service=default/custom-default-http-backend
```

## 動作確認

ブラウザでIngressのIPにアクセスすると404.htmlが反映されています。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/241424/11b62cf7-9153-6d34-42e4-8394384ab536.png)

以上です。

# 補足

defaultbackendは残しています。メモリの無駄なので消したいところですが、製品が初期導入するものなので、消していいかの判断がつきませんでした。

# 参考: ICPのDefault Backend
初期状態では[ibmcom/defaultbackend](https://hub.docker.com/r/ibmcom/defaultbackend/)イメージを使用したサービスがデプロイされています。このイメージについての詳細な情報が全くないのですが、恐らくIngressのソースにある[404-server](https://github.com/kubernetes/ingress-nginx/tree/master/images/404-server)が使われていると推測されます。ソースを見るとわかるとおり、/に対して404を、/healthzに対して200を返すだけのサーバです。これはIngressのProbeに対応した最低限の実装をしているものになります。