お勧めできないKubernetesの〇〇集

* 完全に個人の独断と偏見に基づく、Kubernetes関連でお勧めできない製品・行為を紹介します。
* なぜこんな記事を書いたか
  * 基本的に過去の自分の失敗や、過去に調査・検討してダメだった内容の共有です
  * 同じ失敗や同じ調査・検討する無駄が減らせれば、という思いです
  
---

# 凡例
* お勧めしない度：私がどれほど強く「やめとけ」と思うかを★1〰5で表します
* お勧めしない理由：理由を解説します
* 代替案：もしあれば挙げます

---

# 製品編

---
## flannel
---

* KubernetesのCNIの一つです。よく使ってる記事を見る気がします

---
### 講評
* お勧めしない度: ★★★★

---

#### お勧めしない理由

---

* 開発が停滞しています
  * v0.10.0が2018年1月に出たきりです
  * そろそろ[次のバージョン](https://github.com/coreos/flannel/issues/1063)はリリースされるみたいですが、積極的に活動してるようには見えないです→延期しそうです
  
　　　　![image.png](https://qiita-image-store.s3.amazonaws.com/0/304012/033b71c7-e3b9-25b2-df10-bf9d53da3e3b.png)

---
 
* 体制に不安があります
  * 主体となって開発していたCoreOSがRedHatに買収され、さらにそのRedHatがIBMに買収されるという状況です 
  * そして、IBMは「IBM Cloud Private 2.1」でflannelではなくcalicoを採用しています。flannelを進めていく雰囲気は無さそうです
     * [DockerとKubernetesを基盤としたプライベートクラウド構築ソフトウェア「IBM Cloud Private 2.1」ベータ版が公開。IBM](https://www.publickey1.jp/blog/17/dockerkubernetesibm_cloud_private_21ibm.html) 

---

* Network Policyをサポートしません

---

* 2018/12/04現在、最新のKubernetes 1.12では動きません
  * [Kubernetes 1.12 and flannel does not work out of the box](https://github.com/coreos/flannel/issues/1044) 
  * Issueにもあるようにワークアラウンドは存在しています

---
     
### 代替案

---

* Calico
  * 開発は活発です
      * 3.2.4や、他のバージョン複数（おそらく旧verのバグフィックス）が2018年11月にリリース
    
　　　　　　![image.png](https://qiita-image-store.s3.amazonaws.com/0/304012/7ee7b305-b131-49f3-8a1c-7f400955398a.png)

---

  * Network Policyをサポートします
  * 事例も多い気がします
      * [Githubで採用](https://githubengineering.com/kubernetes-at-github/)
      * [Kubernetes Cloud Servicesで採用](https://kubedex.com/google-gke-vs-microsoft-aks-vs-amazon-eks/)

---

* Weave
  * 開発はそれなりに行われています
      * 2018年11月にv2.5.0がリリース
  * Network Policyをサポートします
  
---

#### 補足
* CalicoとWeaveの大まかな違い
  * WeaveはVXLANです。外部との通信はNATされます。（src,dst共に）
  * CalicoはBGPでルーティングするのがメインです。
      * しかし調べてみると[ip-in-ipのカプセル化とNATも対応してるようです](https://docs.projectcalico.org/v3.3/usage/troubleshooting/faq#how-do-i-enable-ipip-and-nat-outgoing-on-an-ip-pool)
  * つまりCalicoで十分・・・？
    * Weaveしか使ったことはないのでこれ以上の言及はできないです。 後日気が向いたら比較検証してみます
    
---

## Ceph(Rook)

---

### RookとCephについて
* RookはKubernetes上にストレージを構築するプロジェクトです
* Cephはオブジェクトストレージの製品です
* Rookの記事でよくCephを使っているものを見ますが、私はおすすめしません
* 論旨としてはCephが信用できないので、Rookを使う場合はCeph以外にしましょうという内容です。Rook自体には触れません。

---

### 講評
* お勧めしない度: ★★★★

---

#### お勧めしない理由

---

* 障害事例が多い気がする
  * [Zenlogic障害報告書から考察する分散ストレージCeph](https://www.orangeitems.com/entry/2018/07/17/142851) 
  * [ニフクラのオブジェクトストレージ障害](http://sternes.hatenablog.jp/entry/2018/02/17/110207)
  * [SourceForge.net、インフラ障害で一部機能が利用できない状態に](https://opensource.srad.jp/story/15/07/21/0444225/)

---

* 過去にjewelバージョンで使っていたが、苦痛だった
  * ログが読めない
    * 開発者がソースコードデバッグする視点のログばかりで、運用者が読んでトラシューするようなログでない
    * [cephのbug tracker](https://tracker.ceph.com/projects/rados/issues?page=1&set_filter=1&tracker_id=1)に報告されているログを見てもらえば伝わると思います
       * 雰囲気だけ伝えるために抜粋するとこんな感じです

---
          
```
2018-10-28 23:23:07.173 7ff73e5b8700  1 -- 172.21.15.118:6813/34020 <== osd.0 172.21.15.118:6801/97454 124 ==== rep_scrubmap(1.c e310 from shard 0) v2 ==== 40+0+42 (2203346794 0 3641534724) 0x561093d72d80 con 0x561092add800
2018-10-28 23:23:07.173 7ff71e4f0700 20 osd.3 969 share_map osd.0 172.21.15.118:6801/97454 310
2018-10-28 23:23:07.173 7ff71e4f0700 20 osd.3 969 should_share_map osd.0 172.21.15.118:6801/97454 310
2018-10-28 23:23:07.173 7ff7224f8700  1 -- 172.21.15.118:6813/34020 --> 172.21.15.118:6801/97454 -- MOSDScrubReserve(1.c RELEASE e969) v1 -- 0x56109353aa00 con 0
2018-10-28 23:23:07.173 7ff7224f8700  1 -- 172.21.15.118:6813/34020 --> 172.21.15.118:6801/97454 -- pg_info((query:969 sent:969 1.c( empty local-lis/les=310/311 n=0 ec=282/14 lis/c 310/310 les/c/f 311/311/0 310/310/14))=([0,0] intervals=) epoch 969) v5 -- 0x561092990f00 con 0
2018-10-28 23:23:54.655 7ff73e5b8700  1 -- 172.21.15.118:6813/34020 >> 172.21.15.118:6801/97454 conn(0x561092add800 legacy :-1 s=STATE_CONNECTION_ESTABLISHED l=0).read_bulk peer close file descriptor 46
2018-10-28 23:23:54.655 7ff73e5b8700  1 -- 172.21.15.118:6813/34020 >> 172.21.15.118:6801/97454 conn(0x561092add800 legacy :-1 s=STATE_CONNECTION_ESTABLISHED l=0).read_until read failed
2018-10-28 23:23:54.655 7ff73e5b8700  1 -- 172.21.15.118:6813/34020 >> 172.21.15.118:6801/97454 conn(0x561092add800 legacy :-1 s=OPENED pgs=3 cs=1 l=0).handle_message read tag failed
```

---

* Dockerで構築すると同じjewelでも物理版と比べてソースコードが古く、バグ修正があたっていませんでした
  * これは当時の状況なので今は違うかも 
* 障害よく起きてました。。。
  * 構築の仕方が悪かった可能性もあります。
     * かなり小規模かつ社内利用の緩い環境だったので大ごとにはなりませんでしたが。。

---

* お勧めしない度★5にしない理由は次を考慮してです
   * 今の最新版はもしかすると違うかもしれない
   * 私が悪かっただけで実は普通の人ならトラブルなく運用できたかも
        * (私の前任者もしょっちゅうcephの障害対応してましたが) 
   * スケールアウト等、メリットも多い製品

---

### 代替案
* Minio
  * 私はこれに乗り換えました
  * 時々障害も起きますが、ceph時代に比べれば全然楽です。ログが読めるのが大きい

---

## Helm

---

* kubernetes上のシステムをパッケージ化するものです。
* kubernetesのyamlを変数で穴埋めする形のテンプレートにすることで使いまわしが効くようにします
* 公式リポジトリからシステムを落としてこれたりします。[LAMP](https://github.com/helm/charts/tree/master/stable/lamp)とか[Elastic-stack](https://github.com/helm/charts/tree/master/stable/elastic-stack)とか。
* そんなに悪くない製品ですが、つらみもあるのでお勧めはしないぐらいの製品です

---

### 講評
* お勧めしない度: ★

---

#### お勧めしない理由

---

* 穴埋め形式のテンプレートのため、次のデメリットがあります
    * 対応項目が増えるほどテンプレートが複雑になり、読みにくくなります
        * 条件分岐とかループとか合わさってくると結構大変です
    * 公式リポジトリからちょっとだけ項目追加したいというときに、自分でテンプレート一式落としてきて編集する羽目になります
        * 穴埋め形式なので、穴が空いていないと何もできない
    * 公式リポジトリからちょっとだけ項目を消したい（不要な設定が入ってる）場合も上と同じです
* 後述のKustomizeの方が有望
 
---
 
### 代替案
* kustomize
  * 穴埋めでなく、複数yamlを組み合わせたり、上書きできるそうです。なので上記のつらみは解決されそう
      * [KustomizeでKubernetes YAMLを管理する](https://deeeet.com/writing/2018/07/10/kustomize/) 
  * kubectlに統合される前提だそうです。つまり将来Kubernetesのデフォルトになることが期待できます

---

# 行為編

---

## タグかshaを指定せずにイメージを使う
* お勧めしない度: ★★★★★
* お勧めしない理由
    * これはよく言われてますよね
    * 指定していないといつかそのyamlは動かなくなります
    * 動かなくなってから動いていたイメージを探す羽目になるかもしれません

---

## DockerHubのイメージがいつまでもあると思う
* お勧めしない度: ★★★
* お勧めしない理由
    * 消されることもそりゃあります
    * imageのsaveをしておくと安心です
      * Dockerfile確保で済ませる場合はBASEイメージの確保が必要です
         * 結局BASEイメージを確保しないといけなくなるので、imageのsaveの方が無難です
    * もしくはPrivate Registryを立ててそこに入れておくと安心です　  

---

## インターネットにホワイトリストアクセス制限の掛かっている環境で使おうとする
* お勧めしない度: ★★★★
* お勧めしない理由
    * DockerHubへのPullに問題が生じます
    * [Docker Registry API v2の仕様上](https://docs.docker.com/registry/spec/api/#pulling-an-image)、イメージのLayerのpull先はリダイレクトが可能です
      * `This endpoint may issue a 307 (302 for <HTTP 1.1) redirect to another service for downloading the layer and clients should be prepared to handle redirects.` 
      * リダイレクト先は当然変わることもありえるので、そのタイミングでイメージがPullできなくなります
    * DockerHubへの直接のPullを制限したい企業であれば別にいいですが。。。
    
---

## マルチテナントで使う
* テナント間のセキュリティを考える必要があったり、悪意あるユーザーの想定をしないといけないような使い方を指しています

* お勧めしない度: ★★
* お勧めしない理由
    * カーネルリソースの競合が起きえます。[記事](https://qiita.com/ozota/items/728f0e838817d4ed7399) 
    * ストレージを使う場合は、データのセキュリティも結構難しいです
      * 内部動作としては、Nodeがマウント→コンテナに見せる、という2段階になります 
      * マウントするのはNodeなので、テナントごとにソースIPで制限する等はできません
      * KubernetesのPVはテナント（namespace）に所属しないオブジェクトで、全テナントに見えるはずです
         * [参考](https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/#not-all-objects-are-in-a-namespace)
    * 基本的にデフォルト設定がマルチテナント向きでないので、かなり手を入れていく必要があります 
      * [pod-security-policy](https://kubernetes.io/docs/concepts/policy/pod-security-policy/) を追加したり等
    * マルチテナントで使うなら今はVMの方がいいかな、という感想です
      * そのうちベストプラクティスが整備されれば、という感じです。

---

## [Twelve-Factor App](https://12factor.net/ja/)を知らずに使う
* お勧めしない度: ★★★
* お勧めしない理由
    * これを知っているとKubernetsの機能に気づかずに残念な使い方をすることが回避できると思います
    * 例えば、Dockerイメージ内に環境固有値（プロキシとか）を埋め込む等です
      * ConfigMapで設定するほうがビルドする手間も少なく、環境変化（プロキシ変更等）にも強くなります
      * Twelve-Factor Appを知っていれば、こういう行為に違和感を持てます
          * （やむをえないケースももちろんありますが） 
      * 基本的にTwelve-Factor AppはKubernetsの機能で実現できます
          * [12FactorをKubernetesのアプリ開発へ適用するコメント](https://qiita.com/MahoTakara/items/27ce2d7c17ae70f8b6b6)

--- 
  
## masterのリソースをけちる
* お勧めしない度: ★★
* お勧めしない理由
    * Kubernetesのノードはmasterに定期的に状態報告します(デフォルトで10s間隔)
      * そのためNodeが増えるとmasterの負荷が上がっていきます
      * 障害検知速度を上げるには報告間隔を短くするのですが、そうすると負荷も当然上がります
          * [参考](https://github.com/kubernetes-sigs/kubespray/blob/master/docs/kubernetes-reliability.md) 
    * masterをHDDのPCに立てたNode10台の環境では`kubectl get nodes`に10秒近くかかってます
      * 障害検知速度を上げてるので、それも原因ではあります 

---


## 異なるアーキテクチャのサーバーが混在したクラスタを組む
* 例えばIAサーバーとPowerが混在したクラスタを組むなどです　

* お勧めしない度: ★★★★★
* お勧めしない理由
    * 通常はKubernetesが動きません
    * 動かない理由は、次のためです
      * 一般的に、IA用にコンパイルしたアプリはPower上では動きません。逆もそうです
      * Kubernetesのシステムコンポーネントには、DaemonSetで全Nodeに配布されるコンテナがあります
          * pauseイメージや、CNIのコンテナ等です
          * 単一イメージなので、IAサーバーかPowerのどちらかでしか動きません
              * そのためIAサーバーとPowerが混在したクラスタでは、どうしてもどれかのNodeでDaemonSetのコンテナが動かないことになります
    * (厳密なことを言えばbeta.kubernetes.io/arcラベルでサーバーアーキテクチャは選択できるので、システムコンポーネントのyamlを書き換えれば不可能ではないですが、お勧めはしません)

---
 
![image.png](https://qiita-image-store.s3.amazonaws.com/0/304012/6dfc8608-6eea-ec01-2af9-dda2cb99a646.png)


---
    
## 証明書更新せずに使い続ける
* お勧めしない度: ★★★★★
* お勧めしない理由
      * 証明書の期限が切れると動かなくなります
      * [デフォルトは1年です](https://blog.manabusakai.com/2018/10/kubernetes-tls-certificate/)
      * Kubernetes1.12から、[更新機能](https://qiita.com/oke-py/items/cf83a174c5e95c9cbe0e)がGAになってます