F5/NGINX Community！に参加してきた【レポート】

# 第1回 F5 / Nginx Community！
本日開催された下記イベントに参加してきました！
https://f5-nginx.connpass.com/event/156307/
今年の3月にF5 Networks社とNginx社が合併してからちょこちょこイベントが開催されてますが、meetup的なのは初めてでしたので参加してみました！
またイベント概要に以下記載があり、現在の業務での課題や悩みを解決する助けになるのではないかと思い参加しました。

>インフラとアプリケーションの開発手法は大きく変化してきています。 これまでのように要件を定義し、時間をかけてインフラやソフトウェアを開発する流れから クラウドやAPIを前提に高速で小さく開発・提供・改修を重ねていく手法がメインストリームになっています。

>また、現在はアプリケーション自体が ビジネスサービスのメインストリームになっており、 その重要性はますます高まっています。 そんな中でアプリケーション開発とインフラ開発、この2つに距離感をもっと縮めたい、 そのような声をたくさん伺っています。

>このコミュニティは ビジネスパワーに直結するアプリケーション開発をより早く、よりカジュアルにするため、 アプリケーション開発、インフラ開発2つの側面を近づけていくことを目標としています。

その参加レポートになります。

# KubernetesのIngressとは？
[What is Ingress?](https://kubernetes.io/docs/concepts/services-networking/ingress/#what-is-ingress)
IngressとはKubernetesの機能であり、クラスター外部から[Service](https://kubernetes.io/docs/concepts/services-networking/service/)へのアクセスをホスト名やパスでルーティングすることができるL7のLoadBalangerとしての役割を持っています。それらの機能をNginxを利用して実現するものがingress-nginxです。
オンプレ環境においてKubernetesを構築した場合、Ingressを作成する機能(Ingress Controller)がないためingress-nginxを利用してIngressを作成します。

めちゃくちゃややこしいのですが、ingress-nginxにも2種類ありまして、

 - Kubernetesコミュニティの管理する `kubernetes/ingress-nginx`
 - Nginx社の管理する `nginxinc/kubernetes-ingress`

があります。はい、もう嫌になりましたね。(笑)
どちらもNginxベースですし、機能もほぼ一緒なので嫌になる気持ちはすごくわかります。
ざっくりとした機能としては、Ingressリソースを作成する際にNginxの設定をKubernetesのConfigMapに保存してルーティングなどを実現します。

>ConfigMap は、実行時に構成ファイル、コマンドライン引数、環境変数、ポート番号、およびその他の構成成果物をポッドのコンテナやシステム コンポーネントにバインドします。

[ConfigMap とは何か](https://cloud.google.com/kubernetes-engine/docs/concepts/configmap?hl=ja)

細かい違いについてはこちらに詳しく書いてあるのでご覧ください。
[kubernetes/ingress-nginxとnginxinc/kubernetes-ingressの違い](https://github.com/nginxinc/kubernetes-ingress/blob/master/docs/nginx-ingress-controllers.md)

今回はNginxのイベントなので`nginxinc/kubernetes-ingress`を取り上げていきます。
こちらはタイプが2種類ありOSS版と有償版のPlusが存在します。そこの違いについても上のリンクに書いてあるので確認してもらえればと思います。
`kubernetes/ingress-nginx`との大きな違いとしてはNginxのSyntaxが使えるところが大きく違うと思います。
この記事はレポートなので、検証などはありませんので大まかに理解してもらえればと思います。

[Ingressドキュメント](https://kubernetes.github.io/ingress-nginx/)

# オンプレ環境でのNginx Ingress利用事例
会社名：株式会社カカクコム
講演者：プラットフォーム技術本部システムプラットフォーム部 坂上　涼 様
スライド：https://www.slideshare.net/RyoSakagami1/nginx-ingress-204839648

本セッションは株式会社カカクコムさんでの、Kubernetesの導入からIngress Controllerの活用に到るまでの経緯を話して頂きました。
株式会社カカクコムさんでは、オンプレ環境にてKubernetesの導入/運用を実施されている事例のお話しです。

### Kubernetesへの道筋
元々Dockerは利用していて、管理の必要性は感じていた。
しかしコンテナオーケストレーションが乱立しており、技術選定に迷っていた。
ここ一年くらいでKubernetesがデファクトスタンダードになってきた感じがあったため、一気にKubernetes舵きりしていった。

**求人サイトのpub/subキューシステム案件**
元々はキューの一部分のみKubernetesの導入を検討していた
キューからメッセージを読み出すconsumerをkafkaを利用して運用していた。
しかし該当の部分がエフェメラルかつ要スケールになっていた。
徐々にスケールなどが必要な範囲が広がった結果、キューシステムまるっとマイクロサービス化することになった。

**Ingressが無い時代**
![no_ingress_nginx.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423088/32a9d88b-33c9-65dd-7682-7fc910294ea6.png)
上記のアーキテクチャーのときは以下のような課題があった。

 - LB設定変更するために開発/インフラ間の調整コストがかかる
 - ポートアサインのコスト
 - LBのプール設定

LBのプロキシ周りで特に苦労した。
プロキシ機能をよしなにしてくれるものが必要だよね -> Ingress Controller欲しい…

**Ingress Controller導入後**
![ingress_nginx.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423088/35617225-05de-f766-445c-3b53d0d7cbcf.png)


LBでのプロキシ設定が不要になり、運用負荷がかなり軽減した。

### IngressとIngress Controller
Ingress 

 - 名前ベースのvirtualhost+L7LB

Ingress Controller

 - ルールに基づいてトラフィックをルーティングする実態
 - GKEやEKSといったクラウドプロバイダー
 - オンプレミスの場合は自前で用意する必要がある。

### オンプレでもIngressしたい
Ingress Controller導入にあたっての製品比較として以下の3つがあった。

 - セルフホスト型では有名なkubernetes公式の`kubernetes/ingress-nginx`
  - https://github.com/kubernetes/ingress-nginx
 - nginxinc(OSS)
  - https://github.com/nginxinc/kubernetes-ingress
 - nginxinc(有償版)

比較検討した結果nginxinc(OSS)を利用することにした。
理由等しては下記が決めてとなった。

 - 脆弱性への対応が早い
 - ソース見て自分たちでカスタマイズできる

Kubernetesの運用に関して以下の流れで実施している

 - 公式のプレーンマニュフェストを利用する
 - [kustomize](https://github.com/kubernetes-sigs/kustomize)を利用してマニュフェストをカスタマイズ
 - algosyncを利用してCDを回す
 - Deploy

**マニュフェストファイルの参考**

```config:nginx.conf
# ホスト設定
server {
  server_name hoge.com;
}

# ルーティング設定
location / {
  return 302 /coffee;
}
```

```yaml:ingress
# ホスト設定
spec:
  rules:
    - host: hoge.com

# ルーティング設定
annotations:
  nginx.org/rewrites:
serviceName=coffee-svc
rewrite=/coffee/"
```


### Ingress Controllerを導入したことによる恩恵

1. メトリクスの可視化
Prometheusのネイティブ対応によってクラスターのメトリクスが詳細に取れるようになった
上記のことからクラスターレベルのトラフィックも容易に監視できるようになった

2. 保守性の工場
フロー図の導線すっきりとしてわかりやすくなった
サービスへのvirtualhostによる名前ベースのルーティングが可能になった

### 注意点

1. Service OK / Ingress NGのケース
Kubernetesのコンポーネントの障害が原因
要モニタリングの整備
モニタリングを細やかにする必要がある

2. Controllerの競合
複数のControllerが存在する場合デフォルトで二重で動作してしまう
起動オプションとアノテーション間でclass一致させる必要がある

# NGINX Ingressを使ってみた話
会社名：ブロードリーフ株式会社
講演者：田端様
スライド：https://www.slideshare.net/KazuyaTabata/201912111f5nginx-community

ブロードリーフ株式会社さんではGKEでIngressとしてNGINXを使ってみようとして検証した際のお話しを聞くことができました。
※下記記事は田端様の同僚の方の記事だそうです。
https://qiita.com/HirokiSakonju/items/dc04c0961fb976cea8c4


### Ingressって？
外部にKubernetesのサービスを公開するための入り口

### NGINX Ingressを作ってみよう
Terraformを利用してクラスタ/ノードをGKE上に作成している

マニュフェスト
`kind`で`Service`とか`Pod`とか`Ingress`を指定してる

```yaml:Service
apiVersion: v1
kind: Service
metadata:
  name: hoge-api
  namespace: hoge-namespace
  labels:
    app: hoge-api
spec:
  type: (LoadBalancer->) NodePort
  ports:
  - port: (80->)8080 
    targetPort: 8080
    protocol: TCP
  selector:
    app: hoge-api
```

```yaml:Pod
apiVersion: v1
kind: Pod
metadata:
  name: "hoge"
  labels:
    name: hoge-fuga
    role: web
spec:
  containers:
    - image: hoge/hoge-image:latest
      name: hoge-fuga
      ports:
        - containerPort: 8080
      env:
        - name: MESSAGE
          value: hogehoge
```

```yaml:Ingress
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: hoge-ingress
  namespace: hoge-namespace
  annotations:
    kubernetes.io/ingress.global-static-ip-name: hoge-ipaddress
spec:
  rules:
  - host: hoge.example.com
    http:
      paths:
      - backend:
          serviceName: hoge-api
          servicePort: 8080
```

Helm使ってデプロイしてる
`helm install --name NGINX-ingress`みたいな感じ

### ExternalNameを設定してみよう
GKEのIngressだと設定できない。
サービスのCNAME(IPでもOK)
DNSの名前解決的な感じでサービスの口を用意する

GKEなどのプロバイダー系はある程度テンプレ化されていて使い出しやすいが、細かい設定が効かない。。
NGINX Ingressだと`annotation`が結構細かい設定ができて痒いところに手が届く
ある程度運用が進んだフェーズで必要になってくると思う

# 「KubernetesとNginxを組み合わせた効率的なオートスケール」
会社名：ウォンテッドリー株式会社
講演者：Infrastructure Squad 田中 篤志 様
スライド：https://speakerdeck.com/bgpat/autoscaling-with-Kubernetes-and-nginx

ウォンテッドリー株式会社さんでは、プロバイダーによるマネージドサービス(GKEやEKS)がない時代にKubernetes導入されていたそうで、その頃と今の運用やそこに到るまでのお話しを聞くことができました。

### wantedlyでのサービス開発
やっぱりマイクロサービス

 - いろんな言語
  - もともとRubyだった
 - 1クラスターKubernetesクラスタに複数のサービス
  - リソースが足りないため、複数クラスターの管理は向かないと判断している
 - 約100個のマイクロサービス
  - 上記のクラスターにすべて載っている
 - 各エンジニアが開発からデプロイまで行う
  - リリースサイクルにインフラエンジニアが絡んでくることはない

### Nginxを利用したオートスケーリング
負荷に合わせてサーバーを増やしたいという要望から、まずは標準機能でオートスケールを実現した
**Kubernetesの標準機能でオートスケール**

 - Horizontal Pod Autoscaler(HPA)
 - CPU負荷が高い -> pd(サーバー)を増やす
 - 本当にヤバいときは有効
 - 少しリクエストが多いくらいだと何も起きない

-> もっと効率のいい方法を模索した

**より効率的なオートスケール**

 - Custom Metrics + HPA
  - CPU & Memory 標準
 - アプリケーションのメトリクスが使える
 - Nginxのメトリクスが使えるのでは？
  - リバプロとしてNginxがすでにPodに入っていた
  - stub_statusのwritingを処理中のコネクションとしてメトリクス監視している

上記を踏まえ、オートスケール基盤で実施したこと

 - 既存のマイクロサービス作成フローに組み込んだ
 - エンジニアが必ず使うツールの中を大改修
 - 必ずNginxを入れるようにテンプレート修正

### 近況

 - パフォーマンス改善とコスト削減に貢献
  - クラウド上で動いているので、リソースの最適化がKubernetes側でよきにしてくれている
 - ほぼ全てのマイクロサービスに導入された
  - 上述したとおり、約100のマイクロサービスがクラスターにまとまって運用している
 - なかなか手放せない基盤になっている
  - 元々は限られたサービスで実施しようと思っていたが、多くのマイクロサービスで同様のスケーリングを求められるため結果的に多くのサービスが載っている

### 困ったこと

 - 他の基盤(GKE/EKSなど)とかに移れない
 - そろそろメンテナンスが必要
  - Kubernetesのアップデートつらい…

その他参考として、プロビジョニングツールとして[kops](https://github.com/kubernetes/kops)を使っているそうです。
https://aws.amazon.com/jp/blogs/news/configure-kubernetes-cluster-on-aws-by-kops/

# 所感
コンテナ運用に関しては一般的になってきましたが、Kubernetesとなるとまだあまり多くはない印象ですが、今回登壇された各企業様とも長く運用しており知見が溜まっているように感じました。
スモールスタートでもできなさそうな感じではないが、運用範囲を広げた方がメリットはより享受できるのかな、と思いました。
まだまだ弊社ではPoCの段階ではあるので、引き続きキャッチアップしつつ隙あらば導入したいと思います。