コンテンツにスキップ

Kubernetes@IaC

はじめに

本サイトにつきまして、以下をご認識のほど宜しくお願いいたします。


01. Kubernetesの仕組み

アーキテクチャ

Kubernetesは、コントロールコンポーネント、Nodeコンポーネント、から構成される。

kubernetes_architecture


02. 証明書

デフォルトのルート認証局

Kubernetesのルート認証局のルート証明書は、kube-root-ca.crtというConfigMapで定義されている。

apiVersion: v1
kind: ConfigMap
metadata:
  name: kube-root-ca.crt
  namespace: foo
data:
  ca.crt: |
    -----BEGIN CERTIFICATE-----
    *****
    -----END CERTIFICATE-----


デフォルトのSSL証明書

kubernetes_certificates

コンポーネント間でHTTPSプロトコルを使用するためにはクライアント証明書やSSL証明書が必須である。

一方で必須ではないが、通信をさらに安全にするためにクライアント証明書が使用されているところがある。

クライアント証明書の場合、これを使用するクライアント側には、クライアント証明書と秘密鍵の両方を配置することになる。

送信元 宛先 種類 Node上の証明書のマウント先 (kubeadmの場合) 説明
kube-apiserver kubelet クライアント証明書 /etc/kubernetes/kubelet.confファイル (証明書の中身は/var/lib/kubelet/pki/*.pemファイル) kube-apiserverが、kubeletにHTTPSリクエストを送信するための証明書。
kube-apiserver etcd クライアント証明書 記入中... kube-apiserverが、etcdにHTTPSリクエストを送信するための証明書。
クライアント (kubectlクライアント、Kubernetesリソース) のローカルマシン kube-apiserver クライアント証明書 /etc/kubernetes/admin.confファイル クライアントが、kube-apiserverにHTTPSリクエストを送信するための証明書。証明書の値は、kubeconfigファイルのclient-certificate-dataキーに設定されている。証明書に不一致があると、クライアントからのリクエストで、『x509: certificate has expired or is not yet valid』や『error: You must be logged in to the server (Unauthorized)』というエラーになってしまう。
kube-controller-manager kube-apiserver クライアント証明書 /etc/kubernetes/controller-manager.confファイル kube-controller-managerがkube-apiserverにHTTPSリクエストを送信するための証明書。証明書とは別に、kubeconfigファイルも必要になる。
kube-scheduler kube-apiserver クライアント証明書 /etc/kubernetes/scheduler.confファイル kube-schedulerがkube-apiserverにHTTPSリクエストを送信するための証明書。証明書とは別に、kubeconfigファイルも必要になる。
その他のコンポーネント kube-apiserver SSL証明書 記入中... kube-apiserverが各コンポーネントからHTTPSリクエストを受信するための証明書。
kube-apiserver kubelet SSL証明書 記入中 kubeletが、kube-apiserverからのHTTPSリクエストを受信するための証明書。
kube-apiserver front-proxy SSL証明書 記入中... front-proxyが、kube-apiserverからのHTTPSリクエストを受信するための証明書。


SSL証明書の期限

▼ 期限の確認方法

各SSL証明書の有効期限は1年間である。

証明書は、KubernetesリソースのConfigのclient-certificate-dataキー配下に設定されている。

opensslコマンドの標準入力にこれを渡すと、証明書の期限を確認できる。

Kubernetesでは非常に多くの証明書があるため、期限切れの証明書を特定することは大変である。

$ cat <証明書が設定されたConfigのマニフェストへのパス> \
    | grep client-certificate-data \
    | cut -f2 -d : \
    | tr -d ' ' \
    | base64 -d \
    | openssl x509 -noout -dates


notBefore=Dec  9 09:31:55 2020 GMT # 開始日
notAfter=Jan 10 09:31:55 2022 GMT  # 終了日

Configによっては、証明書のパスが設定されている場合がある。

その場合は、opensslコマンドで直接的にこれを指定する。

$ openssl x509 -noout -dates -in <証明書へのパス>

▼ 更新方法

kubeletプロセスの実行時に、--rotate-certificatesオプションを有効化すると、証明書の更新処理を自動化できる。


03. マルチテナント

マルチテナントとは

各Kubernetesリソースの処理範囲を制限するために、Kubernetesリソースをグルーピングする。


ハード vs ソフト

▼ ハードマルチテナンシー

信頼できる開発者のみがClusterにリクエストを送信する場合に、ヒューマンエラーを防ぐ目的でマルチテナント化する。

例えば、Cluster内にリクエストを送信する開発者が、プロダクトの開発チーム (フロントエンドチーム、バックエンドチーム、インフラチーム) の場合である。

▼ ソフトマルチテナンシー

信頼できない開発者もClusterにリクエストを送信する場合 (例:複数の協力会社がいる、Kubernetesをサービスとして公開している) に、悪意ある操作を防ぐ目的でマルチテナント化する。


X as-a-Service

後述する。


03-02. Clusters as-a-Service

Clusters as-a-Serviceとは

テナントごとにClusterを作成する。


実Cluster分割の場合

▼ 実Cluster単位のテナントとは

テナントごとに、独立したClusterを提供する。

一番簡単である。

▼ 複数のClusterを一元管理

以下のツールを使用して、複数のClusterを一元管理できる。

  • Rancher Multi-cluster Apps
  • Gardener


03-03. Control-planes as-a-Service

Control-planes as-a-Serviceとは

テナントごとに、独立したコントロールプレーンを提供する。


仮想Clusterの場合

▼ 仮想Cluster単位のテナントとは

ホストCluster上にテナントごとに仮想Clusterを作成する。

各仮想Clusterがコントロールプレーンを持ち、これらが独立したコントロールプレーンのコンポーネントを持つ。

仮想Cluster間でコントロールプレーンは分離されている。

▼ 仮想Clusterプロビジョニングツール

アルファベット順

  • kcp
  • tensile-kube
  • vcluster
  • virtual cluster


カスタムリソーステナントの場合

▼ カスタムリソーステナントとは

記入中...


03-03. Namespaces as-a-Service

Namespaces as-a-Serviceとは

テナントごとに、独立したNamespaceを提供する。


階層Namespaceの場合

▼ 階層Namespace単位のテナントとは

Namespaceに親子関係を定義し、各Namespaceをテナントとする。


Namespaceの場合

▼ Namespace単位のテナントとは

単一のCluster上に、テナントごとにNamespaceを作成する。

▼ 実行環境別

実行環境別にNamespaceを分割する。

ただそもそも、Namespaceだけでは実行間環境間の分割が足りず、安全性が低い。

そのため、Cluster自体を分割した方がよい。

▼ チーム別

チーム別にNamespaceを分割する。

著名な書籍に一番多いテナントである。

namespace_teams

▼ 機密性の高さ別

機密性の高さに応じて、Namespaceを分割する。

NamespaceにNetworkPolicyを設定し、Namespace間でKubernetesリソースの通信を制限できる。

▼ ハードウェアリソースの要求量別

コンテナのハードウェアリソースの要求量に応じて、Namespaceを分割する。

NamespaceにResourceQuotaやLimitRangeを設定し、一方のNamespaceでハードウェアリソースの要求量が増えても、他方のNamespaceには影響しないようにできる。

▼ プロダクト別

プロダクト別にNamespaceを分割する。

これは、単一のCluster内で共通基盤のツール (例:ArgoCD、Flux) を動かすような場合に役立つ。

▼ プロダクトのサブコンポーネント別

プロダクトのサブコンポーネント別にNamespaceを分割する。

Namespaceを分割するとシステムを理解しやすくなるため、それだけで分ける意義がある。


Nodeグループの場合

▼ Nodeグループ単位のテナントとは

単一のClusterをNodeグループで分割する。

▼ ハードウェアリソースの要求量別

コンテナのハードウェアリソースの要求量に応じて、Nodeグループを分割する。


03-04. カスタムリソーステナントの場合

カスタムリソーステナントとは

テナントカスタムリソースを使用して、ツール固有のマルチテナントを実現する。

アルファベット順

  • capsule
  • kiosk
  • kubeplus
  • kubezoo


capsule

▼ capsuleとは

capsuleでは、Tenantというカスタムリソースを作成し、テナントを実装する。

Tenantには、複数のNamespaceが所属できる。

capsule_architecture

▼ テナントの実装

*実装例*

fooチームが使用するfooテナント (foo-tenant) を作成する。

apiVersion: capsule.clastix.io/v1beta2
kind: Tenant
metadata:
  name: foo-tenant
spec:
  owners:
    - name: foo-team
      kind: Group

capsule.clastix.io/tenantキーを使用して、fooチームが操作するNamespaceをfooテナントに所属させる。

kind: Namespace
apiVersion: v1
metadata:
  name: foo-1
  labels:
    capsule.clastix.io/tenant: foo-tenant
---
kind: Namespace
apiVersion: v1
metadata:
  name: foo-2
  labels:
    capsule.clastix.io/tenant: foo-tenant


kiosk

▼ kioskとは

kioskでは、Accountというカスタムリソースを作成し、テナントを実装する。

SpaceはNamespaceと紐づいている。

Accountは、Spaceを介して、複数のNamespaceを管理する。

▼ テナントの実装

*実装例*

fooチームが使用するfooテナント (foo-account) を作成する。

apiVersion: tenancy.kiosk.sh/v1alpha1
kind: Account
metadata:
  name: foo-account
spec:
  subjects:
    - kind: Group
      name: foo-team
      apiGroup: rbac.authorization.k8s.io
  space:
    templateInstances:
      - spec:
          template: space-template

Space (foo-space) を作成し、Account (foo-account) に所属させる。

apiVersion: tenancy.kiosk.sh/v1alpha1
kind: Space
metadata:
  name: foo-space
spec:
  account: foo-account

またTemplateを使用して、Namespace内の制限に関するKubernetesリソース (例:NetworkPolicy、LimitRange、など) を一括して設定する。

apiVersion: config.kiosk.sh/v1alpha1
kind: Template
metadata:
  name: space-template
resources:
  manifests:
    - kind: NetworkPolicy
      apiVersion: networking.k8s.io/v1
      metadata:
        name: deny-cross-ns-traffic
      spec:
        podSelector:
          matchLabels:
        ingress:
          - from:
              - podSelector: {}
    - apiVersion: v1
      kind: LimitRange
      metadata:
        name: space-limit-range
      spec:
        limits:
          - default:
              cpu: 1
            defaultRequest:
              cpu: 0.5
            type: Container

実装方法がなかなか複雑で、移行の実装方法は記入中...


KubeZoo

▼ KubeZooとは

KubeZooでは、Tenantというカスタムリソースを作成し、テナントを実装する。

SpaceはNamespaceと紐づいている。

Accountは、Spaceを介して、複数のNamespaceを管理する。