備忘録：kubernetes/EKS基礎①(k8sコンポーネント)

# 備忘録

* k8sのリソース
* EKSの運用
* Fargateの制限　など

## 簡単に試す方法
Docker Desktopで```Enable Kubernetes```を有効にするだけ

![スクリーンショット 2022-12-07 8.33.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/b722e3b3-6b3a-ebf3-26b0-c698b221b460.png)
　
## 基本的なリソース

![スクリーンショット 2022-12-07 8.33.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/fbfff6f0-2303-2867-afd3-8af5862e8428.png)

### Container
実際に稼働している```Container```。コンテナイメージから作成される。
### Pod
```Container```をまとめたもの。1つ以上の```Container```で構成される。```Pod```間で利用するストレージを含む場合もある。
### ReplicaSet
レプリカ(同一構成のPod)の個数を管理するリソース。```Deployment```リソースによって定義される。
### Deployment
どういったコンテナが何個必要かを定義する。ここから```ReplicaSet```や```Pod```、```Container```が作成される。
### Service
```Pod```へのアクセスを管理する。```Serive```に定義された方法でアクセスすることよって```Pod```へのアクセスを抽象化する。

## 基本的なリソースの簡単な検証

### 概要

nginxのイメージを使用して```http://localhost:30080```に接続するとどちらかのPodに接続する構成を作成する。
Serviceで接続の箇所、DeploymentでPodの箇所を定義する。

![スクリーンショット 2022-12-07 9.34.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/5f7ed518-5e8f-181e-e66e-a3f1ebfdf30b.png)

### 準備
下記yamlファイルを準備する。

* Deploymentリソースの定義ファイル

```yaml:nginx-deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx-app
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx-app
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
```

* Serviceリソースの定義ファイル

```yaml:nginx-service.yml
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  type: NodePort
  ports:
  - port: 8080
    targetPort: 80
    protocol: TCP
    nodePort: 30080
  selector:
    app: nginx-app
```

### 作成

* Deploymentリソースの作成と確認

```shell
% kubectl apply -f nginx-deployment.yml
deployment.apps/nginx-deployment created
% kubectl get pods
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-xxxxxxxxxx-xxxxx   1/1     Running   0          10s
nginx-deployment-xxxxxxxxxx-xxxxx   1/1     Running   0          10s
```
* Serviceリソースの作成と確認

```shell
% kubectl apply -f nginx-service.yml
service/nginx-service created
% kubectl get services
NAME            TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)          AGE
kubernetes      ClusterIP   xx.xx.xx.xx   <none>        443/TCP          18h
nginx-service   NodePort    xx.xx.xx.xx   <none>        8080:30080/TCP   18s
```
* アクセス確認
ブラウザから```http://localhost:30080```にアクセス

![スクリーンショット 2022-12-07 9.41.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/d78d8f05-4ae4-b308-6bb0-88ff3e132312.png)

### 削除

* Deployment/Serviceリソースの削除

```shell
% kubectl delete -f nginx-deployment.yml
deployment.apps "nginx-deployment" deleted
% kubectl delete -f nginx-service.yml
service "nginx-service" deleted
% kubectl get pods
No resources found in default namespace.
% kubectl get services
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   xx.xx.xx.xx  <none>        443/TCP   18h
```
## kubernetesのコンポーネント

https://kubernetes.io/ja/docs/concepts/overview/components/

![スクリーンショット 2022-12-15 11.38.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/86f2e6a1-d461-1e6e-1256-e6eb4503acc0.png)

* kube-apiserver
kubectlの情報を受け取ってNodeやPodのスケジューリングを制御

* kube-scheduler
新しいPodをどのNodeに配置するかをスケジューリング

* kube-controller-manager
複数のコントローラーから構成。Nodeで実行されるワークロードの制御

* cloud-controller-manager
AWSなどのクラウドプロバイダが提供するサービスと連携

* etcd
マニフェストをキーバリューストアで管理

* kubelet
Podがマニュフェスト通りの状態であるか確認

* kubeproxy
クラスタ内外のネットワークトラフィックの制御

上記の```Deployment```を```apply```するのを例に取ると
* マニフェスト（yamlファイル）を作成する
* ```kubectl apply```で適用することによって、```kube-apiserver```経由で```etcd```に登録される
* ```kube-controller-manager```が必要なPodを起動するように```etcd```に登録する
* ```kube-scheduler```が```etcd```から情報を取得して、Podを起動するノードを決定
* ```kubelet```が起動すべきPodを検知してPodを起動する

## その他リソース

### Namespace
クラスターを論理的に分割して管理する仕組み

```yaml
apiVersion: v1
kind: Namespace
metadata:
  name: k8s-test
```

下記で確認出来る
```
kubectl config get-contexts
```

### CronJob
k8s上で定期的にプログラムを実行する仕組み
1分毎にnginxコンテナが増える
```yaml:nginx-cron.yml
apiVersion: batch/v1
kind: CronJob
metadata:
  name: nginx-scheduled
spec:
  schedule: "*/1 * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
            - name: nginx-scheduled
              image: nginx
              imagePullPolicy: Always
          restartPolicy: OnFailure
```

Cronjobを消すとコンテナも消える
```
kubectl delete cronjob nginx-scheduled
```

### DeamonSet
定義したPodが各ノードに1つずつ起動する
ログ収集用のPodを起動する場合、サイドカーパターンの他にDeamonSetが使用出来る。

![スクリーンショット 2022-12-13 13.20.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/310c7188-d828-7cc0-12f4-b9e4ab5ad676.png)

### StatefulSet
k8sクラスタ内で永続データを扱う時に使用する
安定的なネットワークIDと永続ストレージが提供される

### Secret
機密情報を環境変数として引き渡し。Pod起動時にSecretに情報を取りに行く
base64エンコードされているだけなので安全ではない。kubesealで暗号化する

```yaml
apiVersion: v1
kind: Secret
type: Opaque
metadata:
  name: user-pass
stringData:
  user-name: ${USER_NAME}
  user-password: ${USER_PASSWORD}
```

参照する側のリソース
```yaml 
env:
  - name: USER_NAME
    valueFrom:
      secretKeyRef:
        key: user-name
        name: user-pass
  - name: USER_PASSWORD
    valueFrom:
      secretKeyRef:
        key: user-password
        name: user-pass
```

### ConfigMap
機密情報でない情報を環境変数として引き渡し

```yaml 
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  app-name: web-server
  app-url: http://example.co.jp
```

参照する側のリソース
```yaml
env:
  - name: APP_NAME
    valueFrom:
      configMapKeyRef:
        key: app-name
        name: app-config
  - name: APP_URL
    valueFrom:
      configMapKeyRef:
        key: app-url
        name: app-config
```

# EKS
運用時に考慮するポイントなど

## セキュリティ関連

### IAMを使用した認証

https://aws.amazon.com/jp/premiumsupport/knowledge-center/eks-iam-permissions-namespaces/

![スクリーンショット 2022-12-15 9.32.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/ef4b443b-7a64-5b16-a4ae-a197dfb16126.png)

* ```aws-auth```:ユーザとGroup、IAMロールの関連付け
* ```RoleBinding```:GroupとRoleの関連付け
* ```Role```:許可する操作の定義


### Pod Security Admission
Podの分離レベルを定義して、レベル毎にポリシーを定義。Podの振る舞いを制限する。
分離レベル：```privileged```,```baseline```,```restricted```
ポリシー:```enforce```,```warn```,```audit```

https://kubernetes.io/ja/docs/concepts/security/pod-security-admission/

### Network Policies
Pod間のIngress、Egress通信の制御が可能。セキュリティグループのような感じ

https://kubernetes.io/docs/concepts/services-networking/network-policies/


## 監視

DeamonSetで各ノードにCloudWatch　Agent用のPodとFluentd用のPodを置く構成。ノードへのIAMロールのアタッチとPodが使用するService Accountの作成が必要。
※Fargateの場合はDeamonSet利用不可

![スクリーンショット 2022-12-15 8.37.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/bcc77374-f19f-bd64-defc-66866d4db15b.png)

### メトリクス監視
Pod毎のメトリクス監視をする場合、CloudWatch Container Insightを使用。ノード内に配置したCloudWatch Agent経由で送信。

### ログ監視
Podのログがノード内のディレクトリに出力される。Fluentdでこのディレクトリを監視してCloudWatch Logsに上げる。

## リソース関連

### Podのリソース制限
Deploymentの定義で制限

* ```requests```：Podデプロイ時にホスト側に最低限求める要求量
* ```limits```：Podが使用出来るリソース上限
```yaml
spec:
  containers:
  - name: app
    image: images.my-company.example/app:v4
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"
```

### オートスケーリング
Cluster AutoscalerかKarpenter。あとはサービスのオートスケールとしてHorizontal Pod Autoscaler (HPA)がある。
* Cluster Autoscaler:Podがノード上にデプロイ出来ない時（requestsr量を確保出来ない時）にステータスがPendingとなる。この時にノード追加。

* Horizontal Pod Autoscaler (HPA)
Podのリソース使用量に応じてPodのスケールアウト、スケールイン

# Fargate利用時の制限
## Log関連
Fargateではノード:Podは1:1で起動されるため、DeamonSetの利用が出来ない。
現在はFluent Bitを使用した組み込みルータを使用した方法が多い。

https://aws.amazon.com/jp/blogs/news/fluent-bit-for-amazon-eks-on-aws-fargate-is-here-jp/

以前はサイドカーパターンを使用していた。

https://aws.amazon.com/jp/blogs/news/how-to-capture-application-logs-when-using-amazon-eks-on-aws-fargate/

CloudWatch Container Insights の EKS Fargateに対応

https://aws.amazon.com/jp/blogs/news/introducing-amazon-cloudwatch-container-insights-for-amazon-eks-fargate-using-aws-distro-for-opentelemetry/

## Volumeの使用
EFSはサポートされている。EBSはEC2タイプのみ

https://aws.amazon.com/jp/blogs/news/running-stateful-workloads-with-amazon-eks-on-aws-fargate-using-amazon-efs/

## Public IP
Public IPの割り当てが出来ない。そのためNodeportを使用して外部からアクセスする構成は不可

## ELB
CLB/NLBは非対応でALBのみサポート。Service作成時にLoadBalancerを選択するとCLBが作成されるがこれは使用不可

```yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  type: LoadBalancer
  selector:
    app: nginx-service
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 8080
```

## Network Policy
使用不可。Secutiry Groupを使用する。

# 関連記事

https://qiita.com/tkubota/items/349d7529667870439e41

https://qiita.com/tkubota/items/46b487598a49039c76c5

https://qiita.com/tkubota/items/f84468e2d65f1b27fd51