Amazon EKS

##1.Kubernetes(k8s)って##

###1-1 Kubernetes(k8s)とは###
Dockerなど本番環境で実際に動かそうとすると、問題となる箇所があります。

- 複数のサーバホスト上で、リソースを確保して動かすにはどうしたらいいか。
- ダウンタイムなくデプロイするにはどうしたらいいか。
- 負荷に応じてスケールアウト、インするにはどうしたらいいか。

そんな問題を解決するために提供されたのが、Kubernetesであり、
自動デプロイ、スケーリング、アプリ・コンテナの運用自動化のために設計されたオープンソースのプラットフォームです。

Kubernetesはこんなことができるオーケストレーションです。

|機能|説明|
|---|---|
|ホスト管理|ホストで問題があった場合にホスト上で動作させない。<br>既に動作していたコンテナは、他のホストに移動させて動作させることができます。|
|スケジューリング|コンテナを実行する時に、リソース状況を見て、対象のホストを決めたり、タグを使って制御したりすることができます。|
|コンテナの死活監視、オートリカバリ|指定したコンテナ数を維持するために死活監視をしたり、問題がある場合は再起動を実施します。|
|サービスディスカバリ、ロードバランシング|複数のコンテナに分散したり、コンテナ側で通信して処理を実行する。|
|シークレットやアプリケーション設定の管理|複数の環境で動作させる時にも、コンテナ側の設定を共通化し、パラメータによって制御可能です。|
|バッチ実行|指定した時間に実行する。|
|エコシステムとの連携|他社エコシステムとの連携|

Kubernetesは他のオーケストレーターとここが違う！

- さまざまなOSSと組み合わせることにより、柔軟に機能拡張が可能。
- 本格的な宣言的オペレーションとinfrastructure as codeを実現可能。
- クラスター上にデプロイするシステムの構成をコードによって定義。

自前でKubernetesを構築しようとすると、各種コンポーネントの設定やメンテナンスが大変です。
そこで、マネージドサービスとして、提供されたのが、Amazon EKS です。


###1-2 おおまかな全体像###

![image.png](https://qiita-image-store.s3.amazonaws.com/0/280929/f7680365-b24b-51cf-0633-d0b1034270af.png)

- API Server経由で、etcdの操作を行い、etcdの状態に応じてアクションをする仕組みとなっている。
- API Server経由で、etcdの操作を行い、etcdの状態に一致するようにk8sが変更される。
- マネージドサービスの場合、 Kubectlとコンテナのことだけを考えれば良い。

|コンポーネント||
|---|---|
|Master|k8sを管理するコンポーネントが配置されりサーバ群|
|node|コンテナが配置されるサーバ群|
|etcd cluster|高信頼性KVS k8sのデータが保存される|

|Master||
|---|---|
|API Server|etcdへのwrite,readを行うAPIサーバ<br>複数台配置して冗長化構成をとることができる|
|Controller Manager|デプロイするコンテナの個数等を管理する<br>複数台配置できるがリーダは1つだけ|
|Scheduler|コンテナをどのNodeにデプロイするか決める<br>複数台配置できるがリーダは1つだけ|

|Node||
|---|---|
|Container runtime|コンテナのランタイム<br>Docker以外を使用することもできる。|
|Kubelet|Node上に配置されるエージェント<br>コンテナな起動停止を行う。|
|Kube-proxy|コンテナとの接続を保証するためにNodeのNWを管理する|

|Kubectl||
|---|---|
|Kubectl|ユーザがk8sを操作する際に使う|


###1-3 基本的な構成要素####

![image.png](https://qiita-image-store.s3.amazonaws.com/0/280929/20ea9aea-8f0c-e981-5013-fa2f06b0bbe2.png)

|Workload||
|---|---|
|Pod(po)|コンテナデプロイの最小単位|
|ReplicaSet(rs)|デプロイしたPod数を維持するリソース|
|Deployment(deploy)|RollingUpdteするためのReplicaSetを管理するリソース|
|DaemonSet(ds)|書くNodeに1個ずつPodをデプロイするリソース|
|StatefulSet(sts)|Statefulなコンテナのデプロイの対応したリソース|
|Job|Job用のコンテナをデプロイするリソース|
|CronJob|Jobをcron実行するリソース|

**Pod**

- コンテナデプロイの最小単位のことです。
- 1個のPodに複数のコンテナを定義できる。
- 定義された複数のコンテナは必ず同一のNodeのデプロイされる。
- 複数のコンテナは同一のIPアドレスを共有する。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/280929/8cf18d84-046e-69e4-0d34-d15a3737347c.png)![image.png](https://qiita-image-store.s3.amazonaws.com/0/280929/e899fec4-84dc-90df-e640-c32c0cb4421c.png)![image.png](https://qiita-image-store.s3.amazonaws.com/0/280929/8a43bc90-7ae5-c3e5-d21c-6b2f1e4defb0.png)
例えば、複数のコンテナ（コンテナAとコンテナB）があり、このPodをデプロイすると、Pod単位にNICが1個あることとなる。

**ReplicaSet**

- デプロイしたPod数を維持するリソースです。
- Podに付与されているlabelを意識してReplicaSetが制御する。
- 1個のPodにLabelを複数付与できるので、目的の違うPodのLabelの組み合わせが被らないように設計する。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/280929/a2e6e078-95f6-f796-dc14-dc28201de5ef.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/280929/4d16bafb-cd6c-73c7-2755-052cad8001f0.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/280929/c3d19c72-7904-1860-427c-f01e463e36d7.png)![image.png](https://qiita-image-store.s3.amazonaws.com/0/280929/a43f013e-bd51-256b-2b04-6840b0cdb4e4.png)
Podが死んだ場合でもReplicaSetが3になるように維持してくれる。

**Deployment**

- RollingUpdateするためにReplicaSetを管理するリソースです。
- [RollingUpdate](https://qiita.com/esplo/items/b50d7284cb645977aa5e) はシステムがダウンしないように少しずつアップデートをする手段です。

例えば、imageを “1.7.9”->“1.12” に変更してデプロイすると、ReplicaSetも新しく作成され、Podも新しく作成される。

|Configuration||
|---|---|
|Configmap|設定情報をkey-valueの形式で保持するリソース|
|Secret|機密情報を保持するリソース|

**Configmap**

- 設定情報をkey-valueの形式で保持するリソースです。
- 作り方：Manifestを書く。ファイルから作る (–frome-file)。
- 使い方：環境変数とする。Volumeとしてマウントする。

**Secret**

- 機密情報を保持するリソースであり、Secret Typesについては、↓のページで詳しく。
https://docs.koki.io/short/resources/secret/

- Secret ”Type:Opaque”について
 - Key-valueで機密情報を保持する
 - 利用する目的：ID,Password等を格納する
 - Configmapとは別の場所で管理する

|Service||
|---|---|
|ClusterIP| クラスタ内のアクセスを保証する|
|NodePort| クラスタ外からクラスタのPortを指定してアクセスする|
|LoadBalancer| 外部のIPアドレスを使⽤してアクセスする|
|Headless| ホスト名で⽤いてクラスタ内でアクセスする|
|ExternalName| 外部のDNSを使⽤するときに使う|

**ClusterIP**

- クラスタ内のアクセスを保証します。
- サービス名で名前解決をし、クラスタ内のPodへアクセスする。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/280929/af328ee5-f217-163d-310b-e3b8e65baf6b.png)![image.png](https://qiita-image-store.s3.amazonaws.com/0/280929/20beaa2e-d16b-e5e0-5a47-ba0d6c81a471.png)![image.png](https://qiita-image-store.s3.amazonaws.com/0/280929/948dfd68-894a-eb2d-3658-29dcac82b043.png)![image.png](https://qiita-image-store.s3.amazonaws.com/0/280929/d68cf9e7-0484-0d58-276c-0f30526a0b0d.png)![image.png](https://qiita-image-store.s3.amazonaws.com/0/280929/e88dfd21-e0f6-15c4-93a8-263911c37557.png)
例えば、WEBサーバがあり、DBサーバにアクセスするときにDNS名で名前解決するのと同じイメージ。

**NodePort**

- クラスタ外からクラスタのPortを指定してアクセスする。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/280929/aacb0e14-4f4f-e470-0e4b-7b55c61af0d8.png)![image.png](https://qiita-image-store.s3.amazonaws.com/0/280929/20beaa2e-d16b-e5e0-5a47-ba0d6c81a471.png)![image.png](https://qiita-image-store.s3.amazonaws.com/0/280929/e0aad189-86e8-bc14-d4bd-e73a0b3b2d54.png)
例えば、PORT 8080は31076に流すようなイメージになる。

|Namespace||
|---|---|
|Namespace|1つのクラスタの中を仮想のクラスタで分けることができる|

**Namespace**

- 検証、開発環境で1つのクラスタの中で分ける
- 開発チーム単位で分ける

###1-4 kubectlによるユーザーのオペレーション###

基本は、Manifestを作成してk8sを操作する

|コマンド||
|---|---|
|kubectl apply |リソースの作成|
|kubectl delete |リソースの削除|
|kubectl get |リソースの情報を取得|
|kubectl describe |リソースの詳細情報を取得|
|kubectl logs |コンテナのログを確認|
|kubectl exec |コンテナでコマンドを実⾏|


##2.Amazon EKSのTenets##

|Tenet|説明|
|:----------|:----------|
|1| EKSはエンタープライズ企業が本番のワークロードを実行するためのプラットフォームであること。<br>信頼性、可視性、スケーラビリティ、管理の容易さ|
| 2|EKSはネイティブで最新のKubernetesの体験を提供すること現状でKubernetesで実現できることと同じことができる|
| 3| EKSユーザが他のAWSサービスを使うときには、シームレスな連携を実現し不要な作業を取り除くこと|
| 4| EKSチームは積極的にKubernetesプロジェクトに貢献していくこと|



##3.Amazon EKSの仕組み##

|名称|説明|
|-----|-----|
|コントロールプレーン|KubernetesでいうMasterに当たる部分。<br>ここが、フルマネージドとなり、管理する必要がない部分。|
|ワーカーノード|Kubernetesでいうnodeの部分。|

![スクリーンショット 2018-12-01 19.11.30.png](https://qiita-image-store.s3.amazonaws.com/0/280929/d785a7bc-67b6-d802-0443-985a01e99042.png)



##4.Clusterの認証##
Heptio Authenticator を利用することで、AWSのIAM と KubernetesのRBACシステム を連携して認証を行う。

　*Heptio Authenticator ついては詳しくないので↓を参考に
　[heptio-authenticator-awsの使い方](https://qiita.com/mumoshu/items/3869f2f95271d9316aa5)

なので、IAMだけ認証できても、RBACシステムに登録されていないユーザーはクラスタにアクセスできません。

ちなみに、そんなときは以下の項目を確認してトラブルシュートを行います。
・IAMユーザを利用してクラスタを作成しているか。
・heptio-Authenticator-awsが正しくインストールされているか。
・RBACにユーザーが追加されているか。
極基本的な部分ですね。



##5.設定##
**■リソース**
Podの定義で実際に利用するCPU、Memoryのrequests（要求する最小リソース）とlimits（コンテナが利用できる最大リソース）を設定する。
実際に運用する上で指定がないと、意図せずリソースを消費してノードが応答しなくなることがあるので、必ず設定しましょう。

・CPUの制限は、1AWS vCPUごとに100m~1000m(0.1~1)
・Memoryの制限は、メモリサイズに合わせて、MiやGiで指定する。

namespace：kube-system → kubernetesに必要なコンポーネントが動いているため、こちらが消費しているリソース分も含めて計算する。

*ところで、Podって？*
Podとは、Kubernetesでコンテナを管理するための最小単位です。
コンテナを単独で管理するのではなく、グループとして管理することで、コンテナの使いにくさを解消することができます。

**■ヘルスチェック**
・Liveness Prode:ヘルスチェックに失敗すると、Podの再起動が行われます。チェックに成功するまでRunningになりません。
・Rediness Prode:ヘルスチェックに失敗すると、Running状態でもLoad Balancerの振り分け対象から外れ、ユーザからのアクセスを受け付けない状態となります。

成功か失敗かは何で決めるの？
・exec:設定したコードで判定する。
・httpGet:httpでリクエストして、ステータスコードで判定する。
・tcpSocket:tcpコネクションが確立できるかで判定する。
と、それぞれの環境に合わせて設定する。

**■スケジューリング**

|名称|説明|
|-----|-----|
|demonset|必ずnodeには、特定の1つのPodを配置する|
|nodeSelector|指定したLabelのnodeにPodを配置する|
|taint/tolerations|指定したkey=value:effectに一致しないPodは配置しない|
|nodeAffinity|nodeにLabelにある条件を指定し一致したPodを配置する|

・Kubectl describe node node名 → 現在のLabelを確認することができます。
・Kubectl label nodes node名 key=value → key=valueを追加することが可能です。
・spec.affinity.node.Affinity 設定(matchExpressions) を書き、条件に一致(In,Exists)不一致（NOde,DoesNotExists）により、Podを起動するノードを制御することが可能です。


**■オートスケーリング**
ワーカーノードとPodの２つ視点から検討する必要があり、マニフェストに指定する「targetAnerageUtilization」にCPU使用率が近づくようにスケールする。
・Cluster Autoscaler：ワーカーノードのオートスケーリング
・Horizontal Pod AutoScaler：Podのオートスケーリング


##6.トラブルシュート##
何かあったらログをみろ。

・Podのログ
　Kubectl logs pod名　のコマンドで確認
　
・Kuberbetesのログ
　kubectl describe pod Pod名　のコマンドで確認
　kubectl describe node Node名　のコマンドで確認

・Kubelet のログ
　journalctl -u kubelet のSSHで確認



##7.料金##
課金されないように停止したい！
→現状では、クラスターを削除して、不要になったら作成するしかなさそう。

Amazon EKS ワーカーノードは標準の Amazon EC2 インスタンスであり、通常の Amazon EC2 オンデマンドインスタンス価格に基づいて請求されます。


##8.暗号化##
[Mar 1, 2021]今まで新規クラスターへのKMS暗号化には対応していましたが、既存クラスターの機密情報も KMS キーを利用して暗号化できるようになったようです。

https://aws.amazon.com/jp/about-aws/whats-new/2021/03/amazon-eks-supports-adding-kms-envelope-encryption-to-existing-clusters/


##9.クラスターの起動時間##

[Mar 19, 2021]新しいクラスターの作成時間が 40% 短縮され、平均 9 分以内で EKS クラスターを作成できるようになったようです。

https://aws.amazon.com/jp/about-aws/whats-new/2021/03/amazon-eks-reduces-cluster-creation-time-40-percent/