Kubernetes Basics
Last updated
Last updated
AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE) GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE)
このページの元の著者は Jorge です(彼の元の投稿は こちら)
コンテナエンジンでコンテナを実行できる。
スケジュールによりコンテナのミッションを効率的に行う。
コンテナを生かしておく。
コンテナ間の通信を可能にする。
デプロイメント技術を許可する。
情報のボリュームを処理する。
ノード:ポッドまたはポッドを持つオペレーティングシステム。
ポッド:コンテナまたは複数のコンテナを包むラッパー。ポッドは通常、1つのアプリケーションのみを含むべきである(通常、ポッドは1つのコンテナを実行する)。ポッドはKubernetesが実行しているコンテナ技術を抽象化する方法である。
サービス:各ポッドはノードの内部範囲から1つの内部IPアドレスを持つ。しかし、サービスを介して公開することもできる。サービスにもIPアドレスがあり、その目的はポッド間の通信を維持することである。したがって、1つのポッドが死んだ場合、新しい置き換え(異なる内部IPを持つ)がサービスの同じIPでアクセス可能になる。内部または外部として構成できる。サービスは、2つのポッドが同じサービスに接続されているときにロードバランサーとしても機能する。
サービスが作成されると、kubectl get endpoints
を実行して各サービスのエンドポイントを見つけることができる。
Kubelet:主要なノードエージェント。ノードとkubectl間の通信を確立するコンポーネントであり、ポッドのみを実行できる(APIサーバーを介して)。KubeletはKubernetesによって作成されていないコンテナを管理しない。
Kube-proxy:apiserverとノード間の通信(サービス)を担当するサービス。ノードの基本はIPtablesである。経験豊富なユーザーは、他のベンダーからの他のkube-proxyをインストールすることができる。
サイドカーコンテナ:サイドカーコンテナは、ポッド内のメインコンテナと一緒に実行されるべきコンテナである。このサイドカーパターンは、現在のコンテナの機能を変更することなく拡張し、強化する。現在、私たちはアプリケーションがどこでも実行できるようにすべての依存関係をラップするためにコンテナ技術を使用していることを知っている。コンテナは1つのことだけを行い、そのことを非常にうまく行う。
マスタープロセス:
Apiサーバー:ユーザーとポッドがマスタープロセスと通信するための方法である。認証されたリクエストのみが許可されるべきである。
スケジューラー:スケジューリングは、ポッドがノードにマッチすることを確認することを指す。これによりKubeletがそれらを実行できる。どのノードにより多くのリソースが利用可能かを判断するための十分な知性を持ち、新しいポッドをそれに割り当てる。スケジューラーは新しいポッドを開始するのではなく、ノード内で実行されているKubeletプロセスと通信し、新しいポッドを起動する。
Kubeコントローラーマネージャー:レプリカセットやデプロイメントなどのリソースをチェックし、例えば、正しい数のポッドやノードが実行されているかを確認する。ポッドが欠けている場合、新しいポッドを開始するためにスケジューラーと通信する。APIへのレプリケーション、トークン、およびアカウントサービスを制御する。
etcd:データストレージ、永続的、一貫性があり、分散型。Kubernetesのデータベースであり、クラスターの完全な状態を保持するキー-バリューストレージ(各変更はここに記録される)。スケジューラーやコントローラーマネージャーなどのコンポーネントは、どの変更が発生したかを知るためにこのデータに依存する(ノードの利用可能なリソース、実行中のポッドの数...)。
クラウドコントローラーマネージャー:フロー制御とアプリケーションのための特定のコントローラー、つまりAWSやOpenStackにクラスターがある場合。
ノードが複数(複数のポッドを実行)される可能性があるため、Apiサーバーへのアクセスが負荷分散され、etcdが同期される複数のマスタープロセスも存在する可能性があることに注意してください。
ボリューム:
ポッドがデータを作成し、そのポッドが消えるときに失われるべきでない場合、それは物理ボリュームに保存されるべきである。Kubernetesはデータを永続化するためにポッドにボリュームを接続することを許可する。ボリュームはローカルマシンまたはリモートストレージに存在する可能性がある。異なる物理ノードでポッドを実行している場合、すべてのポッドがアクセスできるようにリモートストレージを使用するべきである。
その他の構成:
ConfigMap:サービスにアクセスするためのURLを構成できる。ポッドはここからデータを取得して、他のサービス(ポッド)と通信する方法を知る。これは資格情報を保存するための推奨場所ではないことに注意してください!
Secret:これはパスワード、APIキー...などの秘密データをB64でエンコードして保存する場所である。ポッドはこのデータにアクセスして必要な資格情報を使用できる。
デプロイメント:これはKubernetesによって実行されるコンポーネントを示す場所である。ユーザーは通常ポッドと直接作業しない。ポッドはReplicaSets(複製された同じポッドの数)で抽象化され、デプロイメントを介して実行される。デプロイメントはステートレスアプリケーション用であることに注意してください。デプロイメントの最小構成は名前と実行するイメージである。
StatefulSet:このコンポーネントは、データベースのようなアプリケーション専用であり、同じストレージにアクセスする必要がある。
Ingress:これはアプリケーションをURLで公開するために使用される構成である。これは外部サービスを使用しても行うことができるが、アプリケーションを公開する正しい方法である。
Ingressを実装する場合、Ingressコントローラーを作成する必要がある。Ingressコントローラーは、リクエストを受け取り、それを確認し、サービスに負荷分散するエンドポイントとなるポッドである。Ingressコントローラーは構成されたIngressルールに基づいてリクエストを送信する。Ingressルールは、異なるパスや異なる内部Kubernetesサービスへのサブドメインを指すことができることに注意してください。
より良いセキュリティプラクティスは、Kubernetesクラスターのどの部分も公開しないように、エントリーポイントとしてクラウドロードバランサーまたはプロキシサーバーを使用することである。
どのIngressルールにも一致しないリクエストが受信されると、Ingressコントローラーはそれを「デフォルトバックエンド」に送る。describe
コマンドを使用してIngressコントローラーのこのパラメータのアドレスを取得できる。
minikube addons enable ingress
CAはクラスター内のすべての証明書の信頼されたルートである。
コンポーネントが互いに検証できるようにする。
すべてのクラスター証明書はCAによって署名される。
etcdは独自の証明書を持つ。
種類:
apiserver証明書。
kubelet証明書。
スケジューラー証明書。
Minikubeは、完全なKubernetes環境をデプロイすることなく、Kubernetes上でいくつかのクイックテストを実行するために使用できる。マスターとノードプロセスを1台のマシンで実行する。Minikubeはノードを実行するためにVirtualBoxを使用する。 こちらでインストール方法を確認してください。
Kubectl
は、kubernetesクラスター用のコマンドラインツールです。これは、kubernetes内でアクションを実行したりデータを要求したりするために、マスタープロセスのApiサーバーと通信します。
ダッシュボードを使用すると、minikube が何を実行しているかをより簡単に確認できます。アクセスするための URL は次の場所にあります:
各構成ファイルには3つの部分があります: metadata、specification(起動する必要があるもの)、status(望ましい状態)。 デプロイメント構成ファイルの仕様の中には、実行するイメージを定義する新しい構成構造で定義されたテンプレートがあります:
同じ構成ファイルで宣言されたDeployment + Serviceの例( こちら)
サービスは通常1つのデプロイメントに関連しているため、同じ構成ファイルで両方を宣言することが可能です(この構成で宣言されたサービスは内部からのみアクセス可能です):
外部サービス構成の例
このサービスは外部からアクセス可能です(nodePort
と type: LoadBlancer
属性を確認してください):
これはテストには便利ですが、本番環境では内部サービスのみとアプリケーションを公開するためのIngressを持つべきです。
Ingress設定ファイルの例
これにより、アプリケーションがhttp://dashboard.com
で公開されます。
シークレット構成ファイルの例
パスワードがB64でエンコードされていることに注意してください(これは安全ではありません!)
ConfigMapの例
ConfigMapは、ポッドに与えられる設定であり、ポッドが他のサービスをどのように見つけてアクセスするかを知るためのものです。この場合、各ポッドは、mongodb-service
という名前が、通信できるポッドのアドレスであることを知っています(このポッドはmongodbを実行します):
次に、deployment config内で、このアドレスは次のように指定でき、ポッドのenv内にロードされます:
ボリューム設定の例
さまざまなストレージ構成のyamlファイルの例は、https://gitlab.com/nanuchi/youtube-tutorial-series/-/tree/master/kubernetes-volumesで見つけることができます。 ボリュームは名前空間の中にはありません
Kubernetesは、同じ物理クラスターにバックアップされた複数の仮想クラスターをサポートしています。これらの仮想クラスターは名前空間と呼ばれています。これは、複数のチームやプロジェクトにまたがる多くのユーザーがいる環境での使用を目的としています。数人から十数人のユーザーがいるクラスターでは、名前空間を作成したり考えたりする必要はありません。Kubernetesにデプロイされたアプリケーションの各部分をより良く制御し、整理するために名前空間を使用し始めるべきです。
名前空間は名前のスコープを提供します。リソースの名前は、名前空間内で一意である必要がありますが、名前空間間では一意である必要はありません。名前空間は互いにネストすることはできず、各Kubernetes リソースは1つの 名前空間の中にのみ存在できます。
minikubeを使用している場合、デフォルトで4つの名前空間があります:
kube-system: ユーザーが使用するためのものではなく、触れるべきではありません。マスターとkubectlプロセスのためのものです。
kube-public: 公開アクセス可能なデータ。クラスター情報を含むconfigmapが含まれています。
kube-node-lease: ノードの可用性を決定します。
default: ユーザーがリソースを作成するために使用する名前空間です。
Kubernetesリソースのほとんど(例:ポッド、サービス、レプリケーションコントローラーなど)は、いくつかのネームスペースにあります。しかし、ネームスペースリソースやノード、persistentVolumesなどの低レベルリソースはネームスペースにありません。どのKubernetesリソースがネームスペースにあり、どれがないかを確認するには:
そのコンテキスト内のすべての後続のkubectlコマンドのために、名前空間を保存できます。
HelmはKubernetesのパッケージマネージャーです。YAMLファイルをパッケージ化し、公開およびプライベートリポジトリで配布することを可能にします。これらのパッケージはHelm Chartsと呼ばれます。
Helmは、変数を使用して設定ファイルを生成するテンプレートエンジンでもあります。
シークレットは、パスワード、トークン、またはキーなどの機密データを含むオブジェクトです。このような情報は、Pod仕様やイメージに記載されることがあります。ユーザーはシークレットを作成でき、システムもシークレットを作成します。シークレットオブジェクトの名前は、有効なDNSサブドメイン名でなければなりません。こちらで公式ドキュメントをお読みください。
シークレットには以下のようなものがあります:
API、SSHキー。
OAuthトークン。
資格情報、パスワード(プレーンテキストまたはb64 + 暗号化)。
情報やコメント。
データベース接続コード、文字列… 。
Kubernetesには異なるタイプのシークレットがあります。
ビルトインタイプ | 使用法 |
---|---|
Opaque | 任意のユーザー定義データ(デフォルト) |
kubernetes.io/service-account-token | サービスアカウントトークン |
kubernetes.io/dockercfg | シリアライズされた~/.dockercfgファイル |
kubernetes.io/dockerconfigjson | シリアライズされた~/.docker/config.jsonファイル |
kubernetes.io/basic-auth | ベーシック認証のための資格情報 |
kubernetes.io/ssh-auth | SSH認証のための資格情報 |
kubernetes.io/tls | TLSクライアントまたはサーバーのためのデータ |
bootstrap.kubernetes.io/token | ブートストラップトークンデータ |
Opaqueタイプはデフォルトであり、ユーザーによって定義された典型的なキー-バリューペアです。
シークレットの動作:
以下の設定ファイルは、mysecret
というシークレットを定義し、2つのキー-バリューペアusername: YWRtaW4=
とpassword: MWYyZDFlMmU2N2Rm
を持っています。また、mysecret
で定義されたusername
とpassword
が環境変数SECRET_USERNAME
__ と __ SECRET_PASSWOR
に公開されるsecretpod
というポッドも定義しています。さらに、mysecret
内のusername
シークレットをパス/etc/foo/my-group/my-username
に0640
の権限でマウントします。
etcdは、すべてのクラスターデータのためのKubernetesのバックストアとして使用される、一貫性があり高可用性のキー-バリューストアです。etcdに保存されているシークレットにアクセスしてみましょう:
あなたは、FS内にあるcerts、keys、urlを確認することができます。それを取得すると、etcdに接続できるようになります。
一度通信が確立されると、秘密を取得できるようになります:
ETCDへの暗号化の追加
デフォルトでは、すべてのシークレットはプレーンテキストでetcd内に保存されます。暗号化レイヤーを適用しない限り。以下の例はhttps://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/に基づいています。
その後、作成した設定ファイルの場所を指すように kube-apiserver
の --encryption-provider-config
フラグを設定する必要があります。 /etc/kubernetes/manifest/kube-apiserver.yaml
を修正し、次の行を追加できます:
ボリュームマウント内をスクロールダウンします:
volumeMountsのhostPathまでスクロールします:
データが暗号化されていることの確認
データはetcdに書き込まれるときに暗号化されます。kube-apiserver
を再起動した後、新しく作成または更新されたシークレットは、保存時に暗号化されるべきです。確認するには、etcdctl
コマンドラインプログラムを使用してシークレットの内容を取得できます。
default
名前空間にsecret1
という新しいシークレットを作成します:
etcdctlコマンドラインを使用して、そのシークレットをetcdから読み取ります:
ETCDCTL_API=3 etcdctl get /registry/secrets/default/secret1 [...] | hexdump -C
ここで[...]
はetcdサーバーに接続するための追加引数です。 3. 保存されたシークレットがk8s:enc:aescbc:v1:
で始まっていることを確認します。これはaescbc
プロバイダーが結果のデータを暗号化したことを示します。 4. APIを介して取得したときにシークレットが正しく復号化されていることを確認します:
はmykey: bXlkYXRh
と一致するべきです。mydataはエンコードされているため、シークレットを完全に復号化するにはシークレットの復号化を確認してください。
シークレットは書き込み時に暗号化されるため、シークレットの更新を行うとその内容が暗号化されます:
最終的なヒント:
FSに秘密を保持しないようにし、他の場所から取得してください。
秘密を保護するためにhttps://www.vaultproject.io/をチェックしてください。
AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE) GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE)