diff --git a/src/pentesting-cloud/kubernetes-security/exposing-services-in-kubernetes.md b/src/pentesting-cloud/kubernetes-security/exposing-services-in-kubernetes.md index 8ca9e99bf..16f794cf4 100644 --- a/src/pentesting-cloud/kubernetes-security/exposing-services-in-kubernetes.md +++ b/src/pentesting-cloud/kubernetes-security/exposing-services-in-kubernetes.md @@ -2,11 +2,11 @@ {{#include ../../banners/hacktricks-training.md}} -Kubernetes では、サービスを公開するための**さまざまな方法**があり、**内部**エンドポイントと**外部**エンドポイントの両方からアクセスできます。この Kubernetes の設定はかなり重要で、管理者が**本来アクセスできないはずのサービスへのアクセスを attackers に与えてしまう**可能性があります。 +Kubernetes には **サービスを公開するさまざまな方法** があり、**内部** エンドポイントと **外部** エンドポイントの両方からアクセスできます。この Kubernetes の設定はかなり重要で、管理者が **攻撃者に、本来アクセスできないはずのサービスへのアクセス権** を与えてしまう可能性があります。 ### Automatic Enumeration -K8s がサービスを public に expose する方法を列挙し始める前に、namespace、services、ingresses を list できるなら、public に expose されているものをすべて次の方法で見つけられることを知っておいてください: +K8s がサービスを public に公開するために用意している方法を列挙し始める前に、namespaces、services、ingresses を列挙できるなら、public に公開されているものはすべて次の方法で見つけられることを知っておいてください: ```bash kubectl get namespace -o custom-columns='NAME:.metadata.name' | grep -v NAME | while IFS='' read -r ns; do echo "Namespace: $ns" @@ -20,21 +20,21 @@ done | grep -v "ClusterIP" ``` ### ClusterIP -**ClusterIP** service は、Kubernetes の **default** **service** です。これは、cluster 内の他の app からアクセスできる **cluster 内の service** を提供します。**external access** はありません。 +**ClusterIP** サービスは、**デフォルト**の Kubernetes **service** です。これは、クラスター内の他のアプリがアクセスできる、クラスター**内の service** を提供します。**外部からのアクセスはありません**。 -ただし、Kubernetes Proxy を使用してアクセスできます: +ただし、これは Kubernetes Proxy を使ってアクセスできます: ```bash kubectl proxy --port=8080 ``` -現在、このスキームを使ってKubernetes APIをたどり、servicesにアクセスできます。 +Now, Kubernetes API を通じてこの scheme を使い services に access できます: `http://localhost:8080/api/v1/proxy/namespaces//services/:/` -たとえば、次のURLを使えます。 +例えば、以下の URL を使えます: `http://localhost:8080/api/v1/proxy/namespaces/default/services/my-internal-service:http/` -この service にアクセスするためです: +この service に access するためです: ```yaml apiVersion: v1 kind: Service @@ -52,19 +52,19 @@ protocol: TCP ``` _この方法では、`kubectl` を **認証済みユーザー** として実行する必要があります。_ -すべての ClusterIP を一覧表示します: +すべての ClusterIP を一覧表示する: ```bash kubectl get services --all-namespaces -o=custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,TYPE:.spec.type,CLUSTER-IP:.spec.clusterIP,PORT(S):.spec.ports[*].port,TARGETPORT(S):.spec.ports[*].targetPort,SELECTOR:.spec.selector' | grep ClusterIP ``` ### NodePort -**NodePort** が利用されると、指定されたポートがすべての Nodes(Virtual Machines を表す)で利用可能になります。特定のポート宛ての **Traffic** は、その後体系的に **service にルーティング** されます。通常、この方法は欠点があるため推奨されません。 +**NodePort** が利用されると、指定されたポートがすべての Nodes(Virtual Machines を表す)で公開されます。**Traffic** はこの特定のポートに向けられた後、**service にルーティング**されます。通常、この方法は欠点があるため推奨されません。 すべての NodePorts を一覧表示: ```bash kubectl get services --all-namespaces -o=custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,TYPE:.spec.type,CLUSTER-IP:.spec.clusterIP,PORT(S):.spec.ports[*].port,NODEPORT(S):.spec.ports[*].nodePort,TARGETPORT(S):.spec.ports[*].targetPort,SELECTOR:.spec.selector' | grep NodePort ``` -NodePort 仕様の例: +NodePort の指定例: ```yaml apiVersion: v1 kind: Service @@ -81,30 +81,41 @@ targetPort: 80 nodePort: 30036 protocol: TCP ``` -yaml内で**nodePort**を指定しない**場合**(これは開放されるポートです)、**30000–32767**の範囲のポートが使われます。 +yamlで**nodePort**を**指定しない**場合(これは開かれるポートです)、**30000–32767の範囲**のポートが使われます。 + +NodePortまたはLoadBalancer Servicesを確認する際は、traffic-policyフィールドも調べてください。これらは、特定の送信元から見てどのnodesとbackendsが有用かを変えるためです: +```bash +kubectl get services --all-namespaces \ +-o custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,TYPE:.spec.type,ETP:.spec.externalTrafficPolicy,ITP:.spec.internalTrafficPolicy,AFFINITY:.spec.sessionAffinity,DIST:.spec.trafficDistribution,NODEPORTS:.spec.ports[*].nodePort' +``` +- `externalTrafficPolicy: Local` は、NodePort/LoadBalancer のトラフィックで元の client source IP を保持し、他の node 上の endpoint への forwarding を回避します。local の ready endpoint を持たない node は、Service に他の場所で endpoint があっても traffic を drop する場合があります。 +- `externalTrafficPolicy: Cluster` は default で、任意の node を経由して forwarding できますが、backend logs には実際の external client IP ではなく node IP が記録されることがあります。 +- `internalTrafficPolicy: Local` は、in-cluster の Service traffic を source node に local な endpoint に制限します。これは locality routing であり、authorization boundary ではありません。 +- `sessionAffinity: ClientIP` により、1つの client からの repeated tests が同じ backend に当たりやすくなり、manual checks 中に他の ready endpoint が見えなくなることがあります。 +- `trafficDistribution` と EndpointSlice topology hints は、新しい cluster では同じ zone や同じ node の endpoint を優先できます。これらは hard security policy ではなく routing preference として扱ってください。 ### LoadBalancer -Serviceを外部に**cloud providerのload balancerを使用して**公開します。GKEでは、これにより[Network Load Balancer](https://cloud.google.com/compute/docs/load-balancing/network/)が起動し、すべてのトラフィックをServiceに転送する単一のIP addressが提供されます。AWSではLoad Balancerが起動します。 +**cloud provider's load balancer** を使って Service を外部に公開します。GKE では、[Network Load Balancer](https://cloud.google.com/compute/docs/load-balancing/network/) が起動し、すべての traffic を service に forwarding する単一の IP address が割り当てられます。AWS では Load Balancer が起動します。 -公開された各ServiceごとにLoadBalancerの料金を支払う必要があり、これは高額になることがあります。 +公開された service ごとに LoadBalancer の料金が発生するため、コストが高くなることがあります。 -すべてのLoadBalancersを一覧表示します: +すべての LoadBalancers を一覧表示する: ```bash kubectl get services --all-namespaces -o=custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,TYPE:.spec.type,CLUSTER-IP:.spec.clusterIP,EXTERNAL-IP:.status.loadBalancer.ingress[*],PORT(S):.spec.ports[*].port,NODEPORT(S):.spec.ports[*].nodePort,TARGETPORT(S):.spec.ports[*].targetPort,SELECTOR:.spec.selector' | grep LoadBalancer ``` ### External IPs > [!TIP] -> External IPs は、Load Balancers タイプの services によって exposed され、一般的には external Cloud Provider Load Balancer が使われている場合に使われます。 +> External IPs は type Load Balancers の services によって exposed され、通常は external Cloud Provider Load Balancer が使われている場合に使用されます。 > -> 見つけるには、`EXTERNAL-IP` フィールドに値がある load balancers を確認してください。 +> 見つけるには、`EXTERNAL-IP` フィールドに値が入っている load balancers を確認してください。 -**external IP**(**destination IP**)として cluster に ingress する traffic は、Service port 上で **Service endpoints のいずれかへ routed** されます。`externalIPs` は Kubernetes によって managed されず、cluster administrator の責任です。 +**external IP**(**destination IP** として)で cluster に ingress する traffic は、Service port で **Service endpoints のいずれかへ routed されます**。`externalIPs` は Kubernetes によって managed されず、cluster administrator の責任です。 -`externalIPs` は sensitive な route-control field です。なぜなら、それを設定できる user は、周囲の network がその IP を cluster に route している場合、Service owner が control すべきではない IP address への traffic を claim できてしまうからです。Kubernetes は v1.36 で Service `externalIPs` の deprecation と planned removal を announced しているため、可能なら LoadBalancer integrations や Gateway API のような controller-owned の exposure mechanism を優先し、まだ存在している間もこの field は慎重に restrict/admit してください。 +`externalIPs` は sensitive な route-control field です。なぜなら、これを set できる user は、周囲の network がその IP を cluster に route している場合、Service owner が control すべきでない IP address の traffic を claim できるからです。Kubernetes は v1.36 で Service `externalIPs` の deprecation と planned removal を announce しているため、可能なら LoadBalancer integrations や Gateway API などの controller-owned exposure mechanisms を優先し、この field がまだ存在する間も慎重に restrict/admit してください。 -Service spec では、`externalIPs` は任意の `ServiceTypes` とあわせて指定できます。下の example では、"`my-service`" は "`80.11.12.10:80`" (`externalIP:port`) 上の clients から access できます。 +Service spec では、`externalIPs` は任意の `ServiceTypes` と一緒に指定できます。以下の例では、"`my-service`" は "`80.11.12.10:80`"(`externalIP:port`)上の clients から access できます。 ```yaml apiVersion: v1 kind: Service @@ -123,9 +134,9 @@ externalIPs: ``` ### ExternalName -[**ドキュメントより:**](https://kubernetes.io/docs/concepts/services-networking/service/#externalname) ExternalName 型の Services は、通常の selector である `my-service` や `cassandra` ではなく、**Service を DNS 名にマップ**します。これらの Services は `spec.externalName` パラメータで指定します。 +[**ドキュメントより:**](https://kubernetes.io/docs/concepts/services-networking/service/#externalname) ExternalName 型の Services は、典型的な selector である `my-service` や `cassandra` ではなく、**Service を DNS 名にマップ**します。これらの Services は `spec.externalName` パラメータで指定します。 -例えば、この Service 定義は、`prod` namespace の `my-service` Service を `my.database.example.com` にマップします: +たとえば、この Service 定義は `prod` namespace 内の `my-service` Service を `my.database.example.com` にマップします: ```yaml apiVersion: v1 kind: Service @@ -136,7 +147,7 @@ spec: type: ExternalName externalName: my.database.example.com ``` -ホスト `my-service.prod.svc.cluster.local` を参照すると、cluster DNS Service は値 `my.database.example.com` の `CNAME` レコードを返します。`my-service` へのアクセスは他の Services と同じように動作しますが、重要な違いとして、**redirection は proxying や forwarding ではなく DNS レベルで発生する** ことです。 +ホスト `my-service.prod.svc.cluster.local` を参照すると、cluster DNS Service は値 `my.database.example.com` の `CNAME` レコードを返します。`my-service` へのアクセスは他の Services と同じように機能しますが、重要な違いとして、**redirection は proxying や forwarding ではなく DNS レベルで行われる** 点があります。 すべての ExternalNames を一覧表示します: ```bash @@ -144,26 +155,26 @@ kubectl get services --all-namespaces | grep ExternalName ``` ### EndpointSlices -EndpointSlices は、Service が現在ルーティングしている具体的な backend のアドレスと port を示します。Service に selector がない場合、label だけでは traffic の経路が分からない場合、または一部の backend だけが ready な場合に特に有用です。 +EndpointSlices は、Service が現在ルーティングしている具体的な backend のアドレスとポートを示します。Service に selector がない場合、labels だけでは traffic の経路が分からない場合、または一部の backend だけが ready な場合に特に有用です。 -Services に関連付けられた EndpointSlices を一覧表示します: +Service に関連付けられた EndpointSlices を一覧表示します: ```bash kubectl get endpointslices --all-namespaces kubectl get endpointslice -n -l kubernetes.io/service-name= -o yaml kubectl get endpointslice -n -l kubernetes.io/service-name= \ -o custom-columns='NAME:.metadata.name,ADDR:.endpoints[*].addresses,READY:.endpoints[*].conditions.ready,PORTS:.ports[*].port' ``` -露出をレビューする際は、Service selector と EndpointSlice の `targetRef`、endpoint addresses、readiness conditions、ports を比較してください。selector のない Service は、手動で管理された EndpointSlices と組み合わせることができ、トラフィックを non-Pod や予期しない宛先へルーティングできます。 +露出を確認する際は、Service selector と EndpointSlice の `targetRef`、endpoint addresses、readiness conditions、ports を比較してください。selector のない Service は、手動で管理された EndpointSlices と組み合わせて、トラフィックを non-Pod や予期しない宛先へルーティングできます。 ### Ingress -上記の例とは異なり、**Ingress は service の種類ではありません**。その代わり、**複数の services の前段に置かれ、cluster への “smart router”** またはエントリポイントとして機能します。 +上記のすべての例とは異なり、**Ingress は service の一種ではありません**。代わりに、**複数の services の前面に置かれ、クラスタへの“smart router”** または entrypoint として動作します。 -Ingress ではさまざまなことができますし、**異なる機能を持つ多くの種類の Ingress controllers** があります。 +Ingress では多くのことができ、**異なる機能を持つ多くの種類の Ingress controllers** があります。 -デフォルトの GKE ingress controller は、[HTTP(S) Load Balancer](https://cloud.google.com/compute/docs/load-balancing/http/) を自動で立ち上げます。これにより、path ベースと subdomain ベースの両方で backend services への routing が可能になります。たとえば、foo.yourdomain.com 上のすべてを foo service に送り、yourdomain.com/bar/ path 配下のすべてを bar service に送ることができます。 +デフォルトの GKE ingress controller は、[HTTP(S) Load Balancer](https://cloud.google.com/compute/docs/load-balancing/http/) を自動で立ち上げます。これにより、path ベースと subdomain ベースの両方の routing を backend services に対して行えます。たとえば、foo.yourdomain.com のすべてを foo service に送り、yourdomain.com/bar/ path 配下のすべてを bar service に送ることができます。 -GKE 上の [L7 HTTP Load Balancer](https://cloud.google.com/compute/docs/load-balancing/http/) を使った Ingress object の YAML は、次のようになるかもしれません: +[HTTP(S) Load Balancer](https://cloud.google.com/compute/docs/load-balancing/http/) を使う GKE 上の Ingress object の YAML は、次のようになります: ```yaml apiVersion: networking.k8s.io/v1 kind: Ingress @@ -197,19 +208,19 @@ name: bar port: number: 8080 ``` -すべての ingress を一覧表示します: +すべてのingressesを一覧表示する: ```bash kubectl get ingresses --all-namespaces -o=custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,RULES:spec.rules[*],STATUS:status' ``` -とはいえ、この場合は各項目の情報を1つずつ取得して、より読みやすくするほうがよいです: +この場合は、各項目の情報を1つずつ取得して、より読みやすくするほうがよい: ```bash kubectl get ingresses --all-namespaces -o=yaml ``` ### Gateway API -Gateway API は、Services を公開するための新しい Kubernetes API です。インフラ所有の Gateway objects と、HTTPRoute のようなアプリケーション所有の Route objects を分離します。これは delegation に有用ですが、露出が namespaces をまたいで分割される可能性も意味します。 +Gateway API は、Services を公開するためのより新しい Kubernetes API です。これは、インフラ所有の Gateway オブジェクトと、HTTPRoute のようなアプリケーション所有の Route オブジェクトを分離します。これは委任に便利ですが、公開が namespaces をまたいで分かれる可能性も意味します。 -Gateway API exposure objects を列挙します: +Gateway API の exposure オブジェクトを列挙する: ```bash kubectl get gatewayclasses kubectl get gateways --all-namespaces @@ -217,13 +228,16 @@ kubectl get httproutes --all-namespaces kubectl get gateway -n -o yaml kubectl get httproute -n -o yaml ``` -Gateway listeners、許可された route namespaces、Route の `parentRefs`、hostnames、filters、backend references、そして Route が accepted されたかどうかなどの status conditions を確認してください。共有 Gateway によって accepted された Route は、legacy Ingress object が存在しなくても backend を expose できる場合があります。 +Gateway listeners、allowed route namespaces、Route `parentRefs`、hostnames、filters、backend references、そして route が accepted されたかどうかなどの status conditions を確認します。shared Gateway によって accepted された Route は、legacy Ingress object が存在しなくても backend を expose できます。 ### References - [https://medium.com/google-cloud/kubernetes-nodeport-vs-loadbalancer-vs-ingress-when-should-i-use-what-922f010849e0](https://medium.com/google-cloud/kubernetes-nodeport-vs-loadbalancer-vs-ingress-when-should-i-use-what-922f010849e0) - [https://kubernetes.io/docs/concepts/services-networking/service/](https://kubernetes.io/docs/concepts/services-networking/service/) - [https://kubernetes.io/blog/2026/05/14/kubernetes-v1-36-deprecation-and-removal-of-service-externalips/](https://kubernetes.io/blog/2026/05/14/kubernetes-v1-36-deprecation-and-removal-of-service-externalips/) +- [https://kubernetes.io/docs/concepts/services-networking/service-traffic-policy/](https://kubernetes.io/docs/concepts/services-networking/service-traffic-policy/) +- [https://kubernetes.io/docs/tutorials/services/source-ip/](https://kubernetes.io/docs/tutorials/services/source-ip/) +- [https://kubernetes.io/docs/concepts/services-networking/topology-aware-routing/](https://kubernetes.io/docs/concepts/services-networking/topology-aware-routing/) - [https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/](https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/) - [https://gateway-api.sigs.k8s.io/](https://gateway-api.sigs.k8s.io/) diff --git a/src/pentesting-cloud/kubernetes-security/kubernetes-basics.md b/src/pentesting-cloud/kubernetes-security/kubernetes-basics.md index 3f0a9de59..7dd27586d 100644 --- a/src/pentesting-cloud/kubernetes-security/kubernetes-basics.md +++ b/src/pentesting-cloud/kubernetes-security/kubernetes-basics.md @@ -2,16 +2,16 @@ {{#include ../../banners/hacktricks-training.md}} -**The original author of this page is** [**Jorge**](https://www.linkedin.com/in/jorge-belmonte-a924b616b/) **(read his original post** [**here**](https://sickrov.github.io)**)** +**このページの元の著者は** [**Jorge**](https://www.linkedin.com/in/jorge-belmonte-a924b616b/) **です(元の投稿は** [**こちら**](https://sickrov.github.io)**)** ## Architecture & Basics -### What does Kubernetes do? +### Kubernetes は何をするのか? -- container/s を container engine 上で実行できるようにする。 -- schedule により container を効率的に配置できる。 -- container を生存状態に保つ。 -- container 間の通信を可能にする。 +- container engine で container/s を実行できる。 +- Schedule により containers を効率的に配置できる。 +- containers を稼働し続ける。 +- container 通信を可能にする。 - deployment techniques を可能にする。 - information の volumes を扱う。 @@ -19,45 +19,47 @@ ![Kubernetes architecture diagram showing control plane components, API server, kubelet, kube-proxy, pods, and worker nodes](https://sickrov.github.io/media/Screenshot-68.jpg) -- **Node**: pod または複数の pod を持つ operating system。 -- **Pod**: container 1つ、または複数の container を包む Wrapper。pod には 1つの application だけを含めるべき(そのため通常、pod は 1 container だけを実行する)。pod は kubernetes が実行中の container technology を抽象化するための方法。 -- **Service**: 各 pod は node の internal range から 1つの internal **IP address** を持つ。ただし、service 経由で公開することもできる。**service にも IP address** があり、その目的は pod 間の通信を維持することにある。そのため、1つが死んでも **新しい代替**(異なる internal IP を持つ) **は access 可能** なまま **service の同じ IP** で公開される。internal または external として設定できる。service は、**2つの pod が同じ service に接続** されている場合、**load balancer** としても機能する。\ -**service** が **作成** されると、各 service の endpoints は `kubectl get endpoints` で確認できる。 -- **Kubelet**: 主要な node agent。node と kubectl の間の通信を確立する component で、pod を実行できるのはこれだけ(API server 経由)。kubelet は Kubernetes によって作成されていない container は管理しない。 -- **Kube-proxy**: apiserver と node 間の通信(services)を担当する service。基盤は node 用の IPtables。経験豊富なユーザーは、他ベンダーの別の kube-proxy をインストールすることもできる。 -- **Sidecar container**: main container と一緒に pod 内で動作すべき container。sidecar pattern は、既存の container を変更せずに、その機能を拡張・強化する。現在では、application をどこでも動かせるように必要な依存関係をすべて container technology で包む。container は 1つのことだけを行い、そのことを非常にうまく行う。 +- **Node**: pod または pods を持つ operating system。 +- **Pod**: 1つまたは複数の containers を包む Wrapper。Pod は 1つの application だけを含むべき(そのため通常、pod は 1つの container だけを実行する)。Pod は kubernetes が container technology の実行を抽象化する方法。 +- **Service**: 各 pod は node の内部 range から 1つの内部 **IP address** を持つ。ただし、service 経由でも公開できる。**service にも IP address** があり、その目的は pods 間の通信を維持すること。なので、1つが死んでも **新しい replacement**(別の内部 IP)**は同じ service の IP で公開され、アクセス可能**になる。internal または external に設定できる。service は、2つの pods が同じ service に接続されているとき **load balancer としても機能する**。\ +**service** が **created** されると、`kubectl get endpoints` を実行して各 service の endpoints を確認できる +- **Kubelet**: primary node agent。node と kubectl の間の通信を確立する component で、pods だけを(API server 経由で)実行できる。kubelet は Kubernetes によって作成されていない containers は管理しない。 +- **Kube-proxy**: apiserver と node 間の communications(services)を担当する service。ベースは nodes 用の IPtables。経験豊富なユーザーは他 vendor の別の kube-proxies もインストールできる。 +- **Sidecar container**: main container と一緒に pod 内で実行されるべき containers。 この sidecar pattern は、既存 containers を変更せずにその機能を拡張・強化する。現在では、application がどこでも動くように依存関係すべてを container technology で包むことを知っている。1つの container は1つのことだけを行い、その1つを非常によく行う。 - **Master process:** -- **Api Server:** users と pod が master process と通信するための方法。authenticated request のみを許可すべき。 -- **Scheduler**: Scheduling とは、Pod が Node に割り当てられて Kubelet がそれを実行できるようにすること。どの node により多くの available resources があるかを判断し、新しい pod をその node に割り当てるだけの十分な intelligence を持つ。scheduler は新しい pod を起動するのではなく、node 内で動作している Kubelet process と通信するだけであり、その Kubelet が新しい pod を起動する。 -- **Kube Controller manager**: replica sets や deployments のような resources を確認し、たとえば正しい数の pod や node が実行されているかをチェックする。pod が不足している場合は、scheduler と通信して新しいものを起動する。replication、tokens、account services を API に対して制御する。 -- **etcd**: Data storage、persistent、consistent、distributed。Kubernetes の database であり、cluster の完全な state を保持する key-value storage(各変更はここに記録される)。Scheduler や Controller manager のような component は、どの変更が発生したかを知るためにこの date に依存する(node の available resourced、実行中の pod 数...)。 -- **Cloud controller manager**: flow controls や applications のための特定の controller。例: AWS や OpenStack 上に cluster がある場合。 +- **Api Server:** users と pods が master process と通信するための方法。認証された request のみが許可されるべき。 +- **Scheduler**: Scheduling とは、Pods を Nodes に確実に対応付けて Kubelet がそれらを実行できるようにすること。どの node により多くの利用可能な resources があるかを判断し、新しい pod をそこに割り当てるだけの十分な intelligence を持つ。scheduler は新しい pods を起動しない点に注意。node 内で動作している Kubelet process と通信するだけであり、それが新しい pod を起動する。 +- **Kube Controller manager**: replica sets や deployments のような resources をチェックし、たとえば正しい数の pods や nodes が動作しているかを確認する。pod が不足している場合は、scheduler と通信して新しいものを起動する。replication、tokens、account services を API に対して制御する。 +- **etcd**: Data storage、persistent、consistent、distributed。Kubernetes の database であり、clusters の完全な state を保持する key-value storage(すべての変更はここに記録される)。Scheduler や Controller manager のような Components は、どの変更が発生したか(nodes の利用可能な resources、稼働中の pods 数など)を知るためにこの data に依存する。 +- **Cloud controller manager**: AWS や OpenStack などで、flow controls と applications のための特定の controller。 -複数の node(複数の pod を実行)がある場合、複数の master process もあり得る。その場合、それらの Api server への access は load balanced され、etcd は同期される。 +複数の nodes(複数の pods を実行)があるように、Api server へのアクセスが load balanced され、etcd が同期された複数の master processes がある場合もあることに注意。 **Volumes:** -pod が、pod が消えても失われるべきではない data を作成した場合、それは physical volume に保存すべき。**Kubernetes allow to attach a volume to a pod to persist the data**。volume は local machine または **remote storage** に置ける。異なる physical node 上で pod を実行している場合は、すべての pod が access できるよう remote storage を使うべき。 +pod が、pod が消えても失われてほしくない data を作成した場合、それは physical volume に保存すべき。**Kubernetes allow to attach a volume to a pod to persist the data**。volume は local machine に置くことも、**remote storage** に置くこともできる。異なる physical nodes で pods を実行している場合は、すべての pods がアクセスできるよう remote storage を使うべき。 + +Kubernetes は最近の versions で **image volumes** もサポートする。`image` volume は OCI image または artifact を Pod 内の **read-only** filesystem source として mount し、`volumes[].image.reference` や `volumes[].image.pullPolicy` のような fields を使う。kubelet は container images と同じ credential sources を使って artifact を pull する。これには node credentials、Pod の `imagePullSecrets`、ServiceAccount の `imagePullSecrets` が含まれる。security review では image volumes を runtime inputs および supply-chain dependencies として扱うこと: reference が digest で pinned されているか、どの registry credentials が取得できるか、どこに mount されるか、そして `subPath` が visible directory を制限しているかを確認する。 **Other configurations:** -- **ConfigMap**: services に access するための **URLs** を設定できる。pod はここから data を取得して、他の services(pods)とどう通信するかを知る。ただし、credentials を保存する場所としては推奨されない。 -- **Secret**: passwords、API keys... のような secret data を **store** する場所。B64 で encoded される。pod は必要な credentials を使うためにこの data に access できる。 -- **Deployments**: kubernetes によって実行される component を指定する場所。通常、user は pod を直接扱わず、pod は **ReplicaSets**(同一 pod の複製数)に抽象化され、それらは deployments 経由で実行される。deployments は **stateless** application 向け。deployment の最低限の configuration は name と実行する image。 -- **StatefulSet**: これは **databases** のような application 向けの component で、**同じ storage への access** が必要なものを対象とする。 -- **Ingress**: application を **URL で public に expose** するために使う configuration。external services でも可能だが、application を expose する正しい方法はこちら。 -- Ingress を実装する場合は **Ingress Controllers** を作成する必要がある。Ingress Controller は requests を受け取り、確認し、それらを services に load balance する **pod**。ingress controller は **configure された ingress rules に基づいて request を送信** する。ingress rules は、異なる path や subdomains を異なる internal kubernetes services に向けることができる。 -- より良い security practice は、cloud load balancer や proxy server を entrypoint として使い、Kubernetes cluster の一部を露出しないこと。 -- いずれの ingress rule にも一致しない request を受信した場合、ingress controller はそれを "**Default backend**" に振り分ける。この parameter の address は ingress controller を `describe` すれば取得できる。 +- **ConfigMap**: **URLs** を設定して services にアクセスできる。pod はここから data を取得し、残りの services(pods)とどう通信するかを知る。ただし、credentials を保存する推奨場所ではない。 +- **Secret**: passwords、API keys... のような secret data を B64 で encoded して **store** する場所。pod は必要な credentials を使うためにこの data にアクセスできる。 +- **Deployments**: kubernetes によって実行される components を指定する場所。ユーザーは通常 pods を直接扱わず、pods は **ReplicaSets**(同じ pods の複製数)に抽象化され、それらは deployments 経由で実行される。deployments は **stateless** applications 用である点に注意。deployment の最小設定は name と実行する image。 +- **StatefulSet**: **databases** のように **同じ storage にアクセスする必要がある** applications 向けの component。 +- **Ingress**: application を **URL で public に公開する** ための設定。external services を使っても可能だが、application を公開する正しい方法はこれ。 +- Ingress を実装する場合は **Ingress Controllers** を作成する必要がある。Ingress Controller は **pod** で、request を受け取りチェックし、それらを services に load balance する endpoint になる。ingress controller は **configured された ingress rules に基づいて request を送信する**。ingress rules は、異なる paths や subdomains を異なる internal kubernetes services に向けられる点に注意。 +- より良い security practice は、cloud load balancer や proxy server を entrypoint として使い、Kubernetes cluster のどの部分も exposed にしないこと。 +- どの ingress rule にも一致しない request を受信した場合、ingress controller はそれを "**Default backend**" に direct する。この parameter の address を得るには ingress controller を `describe` できる。 - `minikube addons enable ingress` ### PKI infrastructure - Certificate Authority CA: ![Kubernetes CA and PKI diagram showing API server certificates between clients, scheduler, controller manager, kubelet, and etcd](https://sickrov.github.io/media/Screenshot-66.jpg) -- CA is cluster 内のすべての certificate の trusted root。 -- component 同士が相互に validate できるようにする。 -- すべての cluster certificates は CA により署名される。 +- CA is the trusted root for all certificates inside the cluster. +- Components が互いを validate できるようにする。 +- すべての cluster certificates は CA によって signed される。 - ETCd は独自の certificate を持つ。 - types: - apiserver cert. @@ -68,7 +70,7 @@ pod が、pod が消えても失われるべきではない data を作成した ### Minikube -**Minikube** は、完全な kubernetes environment を deploy することなく、kubernetes 上でいくつかの **quick tests** を行うために使える。**master と node process を 1台の machine 上で** 実行する。Minikube は node を実行するために virtualbox を使う。インストール方法は [**here how to install it**](https://minikube.sigs.k8s.io/docs/start/) を参照。 +**Minikube** は、完全な kubernetes environment を deploy しなくても kubernetes でいくつかの **quick tests** を行うために使える。**master と node processes を1台の machine で**実行する。Minikube は node を実行するために virtualbox を使う。インストール方法は[**こちら**](https://minikube.sigs.k8s.io/docs/start/)。 ``` $ minikube start 😄 minikube v1.19.0 on Ubuntu 20.04 @@ -105,7 +107,7 @@ $ minikube delete ``` ### Kubectl Basics -**`Kubectl`** は kubernetes clusters 用の command line tool です。master process の Api server と通信して、kubernetes 上で actions を実行したり、data を取得したりします。 +**`Kubectl`** は kubernetes clusters のための command line tool です。Master process の Api server と通信して、kubernetes で actions を実行したり、data を取得したりします。 ```bash kubectl version #Get client and server version kubectl get pod @@ -138,7 +140,7 @@ kubectl apply -f deployment.yml ``` ### Minikube Dashboard -dashboardを使うと、minikubeが何を実行しているかをより簡単に確認できます。アクセスするためのURLは次で見つけられます: +dashboard を使うと、minikube が何を実行しているかをより簡単に確認できます。アクセスするための URL は次で見つけられます: ``` minikube dashboard --url @@ -153,12 +155,12 @@ http://127.0.0.1:50034/api/v1/namespaces/kubernetes-dashboard/services/http:kube ``` ### YAML configuration files examples -各 configuration file には 3 つの部分があります: **metadata**, **specification** (**what need to be launch**), **status** (**desired state**)。\ -deployment configuration file の specification 内には、実行する image を定義する新しい configuration structure で定義された template を見つけることができます: +Each configuration file has 3 parts: **metadata**, **specification** (what need to be launch), **status** (desired state).\ +deployment configuration file の specification の中には、実行する image を定義する新しい configuration structure で定義された template を見つけることができます: -**同じ configuration file 内で宣言された Deployment + Service の例(** [**here**](https://gitlab.com/nanuchi/youtube-tutorial-series/-/blob/master/demo-kubernetes-components/mongo.yaml)**)** +**同じ configuration file 内で宣言された Deployment + Service の例(** [**here**](https://gitlab.com/nanuchi/youtube-tutorial-series/-/blob/master/demo-kubernetes-components/mongo.yaml)**から)** -service は通常 1 つの deployment に関連しているため、両方を同じ configuration file に宣言することができます(この config で宣言された service は内部からのみアクセス可能です): +service は通常 1つの deployment に関連付けられるため、同じ configuration file に両方を宣言することが可能です(この config で宣言された service は内部からのみアクセス可能です): ```yaml apiVersion: apps/v1 kind: Deployment @@ -205,7 +207,7 @@ ports: port: 27017 targetPort: 27017 ``` -**外部 service config の例** +**外部サービス設定の例** この service は外部からアクセス可能になります(`nodePort` と `type: LoadBlancer` 属性を確認してください): ```yaml @@ -225,7 +227,7 @@ targetPort: 8081 nodePort: 30000 ``` > [!NOTE] -> これはテストには便利ですが、本番では内部サービスのみを持ち、アプリケーションを公開するために Ingress を使うべきです。 +> これはテストには便利ですが、production では internal services のみを持ち、アプリケーションを公開するために Ingress を使うべきです。 **Ingress config file の例** @@ -245,9 +247,9 @@ paths: serviceName: kubernetes-dashboard servicePort: 80 ``` -**Secrets config fileの例** +**secrets config fileの例** -passwordがB64でエンコードされていることに注目してください(これはsecureではありません!) +passwordがB64でエンコードされていることに注意してください(これはsecureではありません!) ```yaml apiVersion: v1 kind: Secret @@ -258,9 +260,9 @@ data: mongo-root-username: dXNlcm5hbWU= mongo-root-password: cGFzc3dvcmQ= ``` -**ConfigMapの例** +**ConfigMap の例** -**ConfigMap** は、pods に与えられる設定で、他の services をどのように見つけてアクセスするかを理解できるようにします。この場合、各 pod は `mongodb-service` という名前が、通信できる pod のアドレスであることを認識します(この pod は mongodb を実行します): +**ConfigMap** は、pods に与えられる設定で、他の services をどのように見つけてアクセスするかを知るためのものです。この場合、各 pod は `mongodb-service` という名前が、通信できる pod のアドレスであることを知ります(この pod は mongodb を実行します): ```yaml apiVersion: v1 kind: ConfigMap @@ -269,7 +271,7 @@ name: mongodb-configmap data: database_url: mongodb-service ``` -その後、**deployment config** 内で、このアドレスは次のように指定でき、pod の env 内に読み込まれます: +その後、**deployment config** 内で、このアドレスは次のように指定でき、pod の env に読み込まれます: ```yaml [...] spec: @@ -290,18 +292,18 @@ name: mongodb-configmap key: database_url [...] ``` -**volume config の例** +**Example of volume config** -[https://gitlab.com/nanuchi/youtube-tutorial-series/-/tree/master/kubernetes-volumes](https://gitlab.com/nanuchi/youtube-tutorial-series/-/tree/master/kubernetes-volumes) で、さまざまな storage configuration yaml files の例を見つけることができます。\ -**volumes は namespaces の内側にはないことに注意してください** +さまざまな storage configuration yaml files の例は [https://gitlab.com/nanuchi/youtube-tutorial-series/-/tree/master/kubernetes-volumes](https://gitlab.com/nanuchi/youtube-tutorial-series/-/tree/master/kubernetes-volumes) で見つけられます。\ +**volumes は namespaces の中にないことに注意してください** ### Namespaces -Kubernetes は、同じ physical cluster を基盤とする **multiple virtual clusters** をサポートします。これらの virtual clusters は **namespaces** と呼ばれます。これは、複数の team や project にまたがって多くの users がいる環境での使用を想定しています。数人から数十人規模の users の cluster では、namespace を作成したり意識したりする必要は基本的にありません。kubernetes にデプロイされた application の各部分をよりよく管理・整理したい場合にのみ、namespace を使い始めれば十分です。 +Kubernetes は、同じ physical cluster を基盤とする **複数の virtual clusters** をサポートしています。これらの virtual clusters は **namespaces** と呼ばれます。これは、複数の teams や projects にまたがる多くの users がいる環境で使うことを想定しています。数人から数十人程度の users の cluster では、namespaces を作成したり意識したりする必要はありません。kubernetes にデプロイされた application の各部分をより適切に制御し整理したいときに、初めて namespaces を使い始めるべきです。 -Namespaces は名前のスコープを提供します。resources の名前は、同じ namespace 内では一意である必要がありますが、namespace をまたいで一意である必要はありません。Namespaces は互いに入れ子にはできず、**各** Kubernetes **resource** は **1つの** **namespace** にしか属せません。 +Namespaces は names の scope を提供します。resources の names は、同じ namespace 内で一意である必要がありますが、namespace をまたいで一意である必要はありません。Namespaces は互いに入れ子にすることはできず、各 Kubernetes **resource** は **1つの** namespace にしか **属せません**。 -minikube を使用している場合、デフォルトで 4 つの namespaces があります: +minikube を使っている場合、デフォルトで 4 つの namespaces があります: ``` kubectl get namespace NAME STATUS AGE @@ -311,36 +313,36 @@ kube-public Active 1d kube-system Active 1d ``` - **kube-system**: ユーザーが使うためのものではなく、触るべきではありません。master と kubectl プロセス用です。 -- **kube-public**: 公開アクセス可能なデータ。クラスタ情報を含む configmap を含みます -- **kube-node-lease**: ノードの利用可否を判定します +- **kube-public**: 公開アクセス可能なデータ。cluster information を含む configmap を含みます +- **kube-node-lease**: node の availability を決定します - **default**: ユーザーが resource を作成するために使う namespace です ```bash #Create namespace kubectl create namespace my-namespace ``` > [!NOTE] -> ほとんどの Kubernetes resources(例: pods, services, replication controllers など)は、何らかの namespace に属します。However, namespace resources や、nodes や persistenVolumes のような low-level resources は namespace に属しません。どの Kubernetes resources が namespace に属し、どれが属さないかを確認するには: +> Kubernetesのほとんどのリソース(例: pods, services, replication controllers, その他)は、いくつかのnamespace内にあります。ただし、namespace resources や nodes, persistenVolumes のような low-level resources は namespace 内にはありません。どのKubernetes resources が namespace 内にあり、どれが namespace 内にないかを確認するには: > > ```bash > kubectl api-resources --namespaced=true #In a namespace > kubectl api-resources --namespaced=false #Not in a namespace > ``` -その context において、以降のすべての kubectl commands 用に namespace を保存できます。 +その context で、その後のすべての kubectl commands に対して namespace を保存できます。 ```bash kubectl config set-context --current --namespace= ``` ### Helm -Helm は Kubernetes の **package manager** です。YAML ファイルを package 化して、public および private の repositories で配布できます。これらの packages は **Helm Charts** と呼ばれます。 +Helm は Kubernetes の **package manager** です。YAML ファイルをパッケージ化して、public および private repositories に配布できます。これらのパッケージは **Helm Charts** と呼ばれます。 ``` helm search ``` -Helm は、変数を使って config files を生成できる template engine でもあります: +Helmは、変数を使って設定ファイルを生成できるテンプレートエンジンでもあります: ## Kubernetes secrets -**Secret** は、password、token、key などの **sensitive data** を **contains** する object です。このような情報は、Pod specification や image の中に置かれていることがあります。Users は Secrets を作成でき、system も Secrets を作成します。Secret object の name は有効な **DNS subdomain name** でなければなりません。ここを参照してください [the official documentation](https://kubernetes.io/docs/concepts/configuration/secret/). +**Secret** は、password、token、key などの**機密データ**を**含む**オブジェクトです。このような情報は、Pod specification や image の中に入れられることもあります。Users は Secrets を作成でき、system も Secrets を作成します。Secret オブジェクトの name は、有効な **DNS subdomain name** でなければなりません。詳細は[official documentation](https://kubernetes.io/docs/concepts/configuration/secret/)を参照してください。 Secrets には次のようなものがあります: @@ -350,11 +352,11 @@ Secrets には次のようなものがあります: - Information or comments. - Database connection code, strings… . -Kubernetes には、異なる types の secrets があります +Kubernetes にはさまざまな種類の secrets があります | Builtin Type | Usage | | ----------------------------------- | ----------------------------------------- | -| **Opaque** | **arbitrary user-defined data (Default)** | +| **Opaque** | **任意のユーザー定義データ (Default)** | | kubernetes.io/service-account-token | service account token | | kubernetes.io/dockercfg | serialized \~/.dockercfg file | | kubernetes.io/dockerconfigjson | serialized \~/.docker/config.json file | @@ -364,13 +366,13 @@ Kubernetes には、異なる types の secrets があります | bootstrap.kubernetes.io/token | bootstrap token data | > [!NOTE] -> **Opaque type は default で、users が定義する典型的な key-value pair です。** +> **Opaque type はデフォルトで、ユーザーが定義する典型的な key-value pair です。** -**secrets の仕組み:** +**secret の動作:** ![Kubernetes secrets diagram showing secret data reaching the API server and being consumed by a pod](https://sickrov.github.io/media/Screenshot-164.jpg) -以下の configuration file は、`username: YWRtaW4=` と `password: MWYyZDFlMmU2N2Rm` の 2 つの key-value pairs を持つ `mysecret` という **secret** を定義します。また、`secretpod` という **pod** も定義しており、`mysecret` で定義された `username` と `password` を **environment variables** `SECRET_USERNAME` \_\_ および \_\_ `SECRET_PASSWOR` として exposed します。さらに、`mysecret` 内の `username` secret を `/etc/foo/my-group/my-username` の path に `0640` permissions で **mount** します。 +次の configuration file は、`mysecret` という **secret** を定義し、2つの key-value pair `username: YWRtaW4=` と `password: MWYyZDFlMmU2N2Rm` を持ちます。また、`secretpod` という **pod** も定義しており、`mysecret` で定義された `username` と `password` を **environment variables** `SECRET_USERNAME` \_\_ および \_\_ `SECRET_PASSWOR` として公開します。さらに、`mysecret` 内の `username` secret を path `/etc/foo/my-group/my-username` に `0640` permissions で **mount** します。 ```yaml:secretpod.yaml apiVersion: v1 kind: Secret @@ -422,25 +424,25 @@ env | grep SECRET && cat /etc/foo/my-group/my-username && echo ``` ### etcd内のSecrets -**etcd** は、Kubernetesのバックエンドストアとして全クラスタデータに使われる、一貫性があり高可用な **key-value store** です。etcdに保存されている secrets にアクセスしてみましょう: +**etcd** は、Kubernetesのバックエンドストアとして使われる、一貫性があり高可用な **key-value store** で、すべてのクラスタデータを保存します。では、etcdに保存されているSecretsにアクセスしてみましょう: ```bash cat /etc/kubernetes/manifests/kube-apiserver.yaml | grep etcd ``` -FS内にcerts、keys、url’sが配置されているのが見えるでしょう。それらを入手できれば、etcdに接続できるようになります。 +certs、keys、URL は FS 内のどこにあるか分かるでしょう。それを入手できれば、etcd に接続できるようになります。 ```bash #ETCDCTL_API=3 etcdctl --cert --key --cacert endpoint=[] health ETCDCTL_API=3 etcdctl --cert /etc/kubernetes/pki/apiserver-etcd-client.crt --key /etc/kubernetes/pki/apiserver-etcd-client.key --cacert /etc/kubernetes/pki/etcd/etcd/ca.cert endpoint=[127.0.0.1:1234] health ``` -通信を確立すると、secrets を取得できるようになります: +通信を確立できれば、secrets を取得できるようになります: ```bash #ETCDCTL_API=3 etcdctl --cert --key --cacert endpoint=[] get ETCDCTL_API=3 etcdctl --cert /etc/kubernetes/pki/apiserver-etcd-client.crt --key /etc/kubernetes/pki/apiserver-etcd-client.key --cacert /etc/kubernetes/pki/etcd/etcd/ca.cert endpoint=[127.0.0.1:1234] get /registry/secrets/default/secret_02 ``` -**ETCDに暗号化を追加する** +**ETCD に encryption を追加する** -デフォルトでは、すべての secrets は暗号化レイヤーを適用しない限り etcd 内に**平文で保存**されます。以下の例は [https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/](https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/) に基づいています。 +デフォルトでは、すべての secret は encryption layer を適用しない限り etcd 内に **plain** text で保存されます。以下の例は [https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/](https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/) に基づいています ```yaml:encryption.yaml apiVersion: apiserver.config.k8s.io/v1 kind: EncryptionConfiguration @@ -454,20 +456,20 @@ keys: secret: cjjPMcWpTPKhAdieVtd+KhG4NN+N6e3NmBPMXJvbfrY= #Any random key - identity: {} ``` -その後、作成した config file の場所を指すように `kube-apiserver` に `--encryption-provider-config` フラグを設定する必要があります。`/etc/kubernetes/manifest/kube-apiserver.yaml` を変更して、以下の行を追加できます: +その後、作成した config file の場所を指すように `kube-apiserver` の `--encryption-provider-config` フラグを設定する必要があります。`/etc/kubernetes/manifest/kube-apiserver.yaml` を修正して、以下の lines を追加できます: ```yaml containers: - command: - kube-apiserver - --encriyption-provider-config=/etc/kubernetes/etcd/ ``` -volumeMounts で下にスクロールします: +volumeMounts までスクロールしてください: ```yaml - mountPath: /etc/kubernetes/etcd name: etcd readOnly: true ``` -volumeMounts までスクロールして hostPath: を確認してください +volumeMounts までスクロールして hostPath: を探してください ```yaml - hostPath: path: /etc/kubernetes/etcd @@ -476,7 +478,7 @@ name: etcd ``` **データが暗号化されていることの確認** -データは etcd に書き込まれるときに暗号化されます。`kube-apiserver` を再起動した後に、新しく作成または更新された secret は、保存時に暗号化されるはずです。確認するには、`etcdctl` コマンドラインプログラムを使って secret の内容を取得できます。 +データは etcd に書き込まれるときに暗号化されます。`kube-apiserver` を再起動した後、新しく作成または更新された secret は、保存時に暗号化されるはずです。確認するには、`etcdctl` コマンドラインプログラムを使って secret の内容を取得します。 1. `default` namespace に `secret1` という新しい secret を作成します: @@ -490,23 +492,23 @@ kubectl create secret generic secret1 -n default --from-literal=mykey=mydata ここで `[...]` は etcd server に接続するための追加引数です。 -3. 保存された secret が `k8s:enc:aescbc:v1:` で始まっていることを確認します。これは `aescbc` provider が結果のデータを暗号化したことを示します。 +3. 保存された secret が `k8s:enc:aescbc:v1:` で始まっていることを確認します。これは `aescbc` provider が結果の data を暗号化したことを示します。 4. API 経由で取得したときに secret が正しく復号されることを確認します: ``` kubectl describe secret secret1 -n default ``` -は `mykey: bXlkYXRh` と一致するはずです。`mydata` はエンコードされています。secret を完全にデコードするには [decoding a secret](https://kubernetes.io/docs/concepts/configuration/secret#decoding-a-secret) を確認してください。 +は `mykey: bXlkYXRh` と一致するはずです。mydata は encoded されています。secret を完全に decode するには [decoding a secret](https://kubernetes.io/docs/concepts/configuration/secret#decoding-a-secret) を確認してください。 -**secret は書き込み時に暗号化されるため、secret を更新するとその内容は暗号化されます:** +**secret は write 時に暗号化されるため、secret を update するとその content も暗号化されます:** ``` kubectl get secrets --all-namespaces -o json | kubectl replace -f - ``` -**最終的なヒント:** +**Final tips:** -- secrets を FS に保持しないようにし、他の場所から取得するようにしてください。 -- secrets にさらに保護を追加するために [https://www.vaultproject.io/](https://www.vaultproject.io) を確認してください。 +- FS に secrets を置いたままにしないようにし、他の場所から取得してください。 +- secrets をさらに保護するために [https://www.vaultproject.io/](https://www.vaultproject.io) を確認してください。 - [https://kubernetes.io/docs/concepts/configuration/secret/#risks](https://kubernetes.io/docs/concepts/configuration/secret/#risks) - [https://docs.cyberark.com/Product-Doc/OnlineHelp/AAM-DAP/11.2/en/Content/Integrations/Kubernetes_deployApplicationsConjur-k8s-Secrets.htm](https://docs.cyberark.com/Product-Doc/OnlineHelp/AAM-DAP/11.2/en/Content/Integrations/Kubernetes_deployApplicationsConjur-k8s-Secrets.htm) @@ -520,4 +522,12 @@ https://sickrov.github.io/ https://www.youtube.com/watch?v=X48VuDVv0do {{#endref}} +{{#ref}} +https://kubernetes.io/docs/concepts/storage/volumes/#image +{{#endref}} + +{{#ref}} +https://kubernetes.io/docs/tasks/configure-pod-container/image-volumes/ +{{#endref}} + {{#include ../../banners/hacktricks-training.md}} diff --git a/src/pentesting-cloud/kubernetes-security/kubernetes-hardening/kubernetes-securitycontext-s.md b/src/pentesting-cloud/kubernetes-security/kubernetes-hardening/kubernetes-securitycontext-s.md index 52dc909ac..f30cc314c 100644 --- a/src/pentesting-cloud/kubernetes-security/kubernetes-hardening/kubernetes-securitycontext-s.md +++ b/src/pentesting-cloud/kubernetes-security/kubernetes-hardening/kubernetes-securitycontext-s.md @@ -4,81 +4,87 @@ ## PodSecurityContext -[**docsより:**](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core) +[**ドキュメントより:**](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core) -Pod の security context を指定する際には、いくつかの属性を使えます。防御的なセキュリティの観点では、以下を考慮すべきです。 +Pod の security context を指定する際には、いくつかの属性を使えます。防御的なセキュリティの観点では、以下を検討すべきです。 -- **runASNonRoot** を **True** にする +- **runASNonRoot** を **True** - **runAsUser** を設定する -- 可能であれば、**seLinuxOptions** と **seccompProfile** を指定して **permissions** を **制限** する -- **runAsGroup** と **supplementaryGroups** 経由で **privilege** な **group** アクセスを与えない +- 可能なら、**seLinuxOptions** と **seccompProfile** を示して **permissions** を**制限**する +- **runAsGroup** と **supplementaryGroups** で **privilege** の **group** アクセスを**与えない** | Parameter | Description | -|

fsGroup
integer

|

Pod 内の すべての containers に適用される特別な supplemental group。volume の種類によっては、Kubelet がその volume の 所有権を Pod 所有に変更できる:
1. 所有 GID は FSGroup になる
2. setgid ビットが設定される (volume 内で新規作成されたファイルの所有者は FSGroup になる)
3. パーミッションビットは rw-rw---- と OR される。未設定の場合、Kubelet はどの volume の所有権やパーミッションも変更しない

| +|

fsGroup
integer

|

Pod 内のすべての containersに適用される特別な補助 group。いくつかの volume type では、Kubelet がその volume のownership を変更して Pod に所有させることを許可する:
1. 所有 GID は FSGroup になる
2. setgid ビットが設定される(volume 内で作成された新規ファイルは FSGroup 所有になる)
3. permission bits は rw-rw---- と OR される。未設定の場合、Kubelet はどの volume の ownership と permissions も変更しない

| -|

fsGroupChangePolicy
string

| Pod 内で公開される前に、volume の **所有権と権限の変更** をどう行うかを定義する。 | -|

runAsGroup
integer

| container process の entrypoint を実行するための **GID**。未設定の場合は runtime のデフォルトを使う。SecurityContext でも設定可能。 | -|

runAsNonRoot
boolean

| container が non-root user として実行されなければならないことを示す。true の場合、Kubelet は runtime 時に image を検証し、UID 0 (root) で実行されないことを確認する。もしそうなら container の起動に失敗する。 | -|

runAsUser
integer

| container process の entrypoint を実行するための **UID**。未指定の場合、image metadata で指定された user がデフォルトになる。 | -|

seLinuxOptions
SELinuxOptions
More info about seLinux

| すべての containers に適用される **SELinux context**。未指定の場合、container runtime は各 container に対してランダムな SELinux context を割り当てる。 | -|

seccompProfile
SeccompProfile
More info about Seccomp

| この pod で containers が使用する **seccomp options**。 | -|

supplementalGroups
integer array

| container の primary GID に加えて、各 container で実行される最初の process に適用される **groups** のリスト。 | -|

sysctls
Sysctl array
More info about sysctls

| Sysctls は、pod で使用される **namespaced sysctls のリスト** を保持する。container runtime がサポートしていない sysctls を持つ Pods は起動に失敗する可能性がある。 | -|

windowsOptions
WindowsSecurityContextOptions

| すべての containers に適用される Windows 固有の設定。未指定の場合は、container の SecurityContext 内の options が使われる。 | +|

fsGroupChangePolicy
string

| Pod 内で公開される前に、**volume の ownership と permission を変更する**動作を定義します。 | +|

runAsGroup
integer

| container process の entrypoint を実行する **GID**。未設定の場合は runtime の default を使います。SecurityContext でも設定可能です。 | +|

runAsNonRoot
boolean

| container は non-root user として実行しなければならないことを示します。true の場合、Kubelet は runtime で image を検証し、UID 0 (root) で実行しないことを確認し、そうであれば container の起動に失敗します。 | +|

runAsUser
integer

| container process の entrypoint を実行する **UID**。未指定なら image metadata で指定された user が default になります。 | +|

seLinuxOptions
SELinuxOptions
More info about seLinux

| すべての containers に適用される **SELinux context**。未指定の場合、container runtime は各 container に対してランダムな SELinux context を割り当てます。 | +|

seccompProfile
SeccompProfile
More info about Seccomp

| この pod の containers が使う **seccomp options**。 | +|

supplementalGroups
integer array

| container の primary GID に加えて、各 container で最初に実行される process に適用される **groups** の一覧。 | +|

sysctls
Sysctl array
More info about sysctls

| Sysctls は Pod で使われる **namespaced sysctls の一覧**を保持します。container runtime でサポートされていない sysctls を持つ Pod は起動に失敗する場合があります。 | +|

windowsOptions
WindowsSecurityContextOptions

| すべての containers に適用される Windows 固有の設定。未指定の場合は、container の SecurityContext 内の options が使われます。 | ## SecurityContext -[**docsより:**](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core) +[**ドキュメントより:**](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core) -この context は **containers definitions** 内で設定されます。防御的なセキュリティの観点では、以下を考慮すべきです。 +この context は **containers definitions** 内で設定されます。防御的なセキュリティの観点では、以下を検討すべきです。 -- **allowPrivilegeEscalation** を **False** にする +- **allowPrivilegeEscalation** を **False** - 機微な **capabilities** を追加しない(不要なものは削除する) -- **privileged** を **False** にする -- 可能であれば、**readOnlyFilesystem** を **True** にする +- **privileged** を **False** +- 可能なら **readOnlyFilesystem** を **True** - **runAsNonRoot** を **True** にし、**runAsUser** を設定する -- 可能であれば、**seLinuxOptions** と **seccompProfile** を指定して **permissions** を **制限** する -- **runAsGroup** 経由で **privilege** な **group** アクセスを与えない。 +- 可能なら、**seLinuxOptions** と **seccompProfile** を示して **permissions** を**制限**する +- **runAsGroup** で **privilege** の **group** アクセスを**与えない** -**SecurityContext** と **PodSecurityContext** の両方で属性が設定されている場合、**SecurityContext** で指定された値が **優先** されることに注意してください。 +**SecurityContext と PodSecurityContext の両方**で設定された属性については、**SecurityContext** で指定された値が**優先**されることに注意してください。 -|

allowPrivilegeEscalation
boolean

| **AllowPrivilegeEscalation** は、process が親 process よりも **多くの privileges を得られるか** を制御する。この bool は、container process に no_new_privs フラグを設定するかを直接制御する。container が **Privileged** として実行されるか **CAP_SYS_ADMIN** を持つ場合、AllowPrivilegeEscalation は常に true になる | +|

allowPrivilegeEscalation
boolean

| **AllowPrivilegeEscalation** は、process が親 process より**多くの privileges を得られるか**を制御します。この bool は container process に no_new_privs フラグを設定するかどうかを直接制御します。container が **Privileged** として実行されるか **CAP_SYS_ADMIN** を持つ場合、AllowPrivilegeEscalation は常に true です | | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -|

capabilities
Capabilities
More info about Capabilities

| container 実行時に追加/削除する **capabilities**。デフォルトの capabilities セットが既定値。 | -|

privileged
boolean

| privileged mode で container を実行する。privileged containers 内の process は本質的に **host 上の root と同等**。デフォルトは false。 | -|

procMount
string

| procMount は、containers に使用する **proc mount の種類** を示す。デフォルトは DefaultProcMount で、readonly paths と masked paths に container runtime のデフォルトを使う。 | -|

readOnlyRootFilesystem
boolean

| この **container が read-only root filesystem を持つか**。デフォルトは false。 | -|

runAsGroup
integer

| container process の entrypoint を実行するための **GID**。未設定の場合は runtime のデフォルトを使う。 | -|

runAsNonRoot
boolean

| container が **non-root user として実行されなければならない** ことを示す。true の場合、Kubelet は runtime 時に image を検証し、UID 0 (root) で実行されないことを確認する。実行される場合は container の起動に失敗する。 | -|

runAsUser
integer

| container process の entrypoint を実行するための **UID**。未指定の場合、image metadata で指定された user がデフォルトになる。 | -|

seLinuxOptions
SELinuxOptions
More info about seLinux

| container に適用される **SELinux context**。未指定の場合、container runtime は各 container に対してランダムな SELinux context を割り当てる。 | -|

seccompProfile
SeccompProfile

| この container で使用する **seccomp options**。 | +|

capabilities
Capabilities
More info about Capabilities

| container 実行時に追加/削除する **capabilities**。default は default の capabilities セットです。 | +|

privileged
boolean

| privileged mode で container を実行します。privileged container 内の process は本質的に **host 上の root と同等**です。default は false です。 | +|

procMount
string

| procMount は container に使用する **proc mount の type** を示します。default は DefaultProcMount で、readonly paths と masked paths に container runtime の default を使います。 | +|

readOnlyRootFilesystem
boolean

| この **container が read-only の root filesystem を持つか**どうか。default は false です。 | +|

runAsGroup
integer

| container process の entrypoint を実行する **GID**。未設定の場合は runtime の default を使います。 | +|

runAsNonRoot
boolean

| container は non-root user として**実行しなければならない**ことを示します。true の場合、Kubelet は runtime で image を検証し、UID 0 (root) で実行しないことを確認し、そうであれば container の起動に失敗します。 | +|

runAsUser
integer

| container process の entrypoint を実行する **UID**。未指定なら image metadata で指定された user が default になります。 | +|

seLinuxOptions
SELinuxOptions
More info about seLinux

| この container に適用される **SELinux context**。未指定の場合、container runtime は各 container に対してランダムな SELinux context を割り当てます。 | +|

seccompProfile
SeccompProfile

| この container で使う **seccomp options**。 | |

windowsOptions
WindowsSecurityContextOptions

| すべての containers に適用される **Windows 固有の設定**。 | ## Practical workload review checklist -Pod または workload template をレビューする際は、`spec.securityContext` と、`containers`、`initContainers`、`ephemeralContainers` 配下の各 container-level `securityContext` の両方を確認してください。container-level の field は pod-level のデフォルトを上書きできるため、安全そうに見える pod default でも、各 container が安全であるとは限りません。 +Pod や workload template をレビューする際は、`spec.securityContext` と、`containers`、`initContainers`、`ephemeralContainers` 配下の各 container-level `securityContext` の両方を確認してください。container-level の field は pod-level の default を上書きできるため、安全に見える pod default だけでは、すべての container が安全であるとは限りません。 優先して確認すべき高リスクな組み合わせ: -- `privileged: true`。特に `hostPID`、`hostIPC`、`hostNetwork`、`hostPath`、host ports、または runtime socket mounts と組み合わさる場合。 -- `SYS_ADMIN`、`NET_ADMIN`、`SYS_PTRACE`、`SYS_MODULE`、`DAC_READ_SEARCH`、`DAC_OVERRIDE` などの追加 capabilities。 -- attacker-controlled code を実行できる containers での `allowPrivilegeEscalation: true`、または未設定。 -- `seccompProfile: Unconfined`、`procMount: Unmasked`、または機微な workloads で runtime profiles が不足している場合。 -- 信頼できない input を処理する workloads における writable root filesystem や広範な writable volume mounts。 -- マルチテナント namespace での CPU、memory、ephemeral-storage の requests と limits の欠如。 +- `privileged: true`。特に `hostPID`、`hostIPC`、`hostNetwork`、`hostPath`、host ports、runtime socket mounts と組み合わさる場合。 +- `SYS_ADMIN`、`NET_ADMIN`、`SYS_PTRACE`、`SYS_MODULE`、`DAC_READ_SEARCH`、`DAC_OVERRIDE` などの capabilities を追加している。 +- `allowPrivilegeEscalation: true`、または attacker-controlled code を実行できる container で未設定。 +- `seccompProfile: Unconfined`、`procMount: Unmasked`、または機微な workload で runtime profiles が不足している。 +- untrusted input を処理する workload における writable root filesystem や、広範な writable volume mounts。 +- multi-tenant namespace における CPU、memory、ephemeral-storage の requests と limits がない。 +- Pod-level の `spec.resources` budget がない、または非現実的であること、さらに Pod の `resize` subresource に対して `patch` や `update` を持つ principals がいること。対応している cluster では、Pod を作り直さずに稼働中の CPU と memory の desired state を変更できるためです。 -ほとんどの application workloads では、non-root UID で実行し、`runAsNonRoot: true` を設定し、`allowPrivilegeEscalation: false` を設定し、すべての capabilities を drop して必要最小限のものだけを追加し、`seccompProfile: RuntimeDefault` を使い、read-only root filesystem を優先し、host namespaces、hostPath mounts、privileged mode は避けるのが良い baseline です。 +Resource controls は `securityContext` の一部ではありませんが、availability の境界を定義するので同じ workload のレビューで確認してください。最新の Kubernetes では、container-level の `resources` に加えて、Pod-level で `spec.resources` の下に CPU、memory、hugepage の budget を定義できます。sidecars を持つ Pod は、1 つの container に個別の limits がなくても、Pod 全体の envelope で制限される場合があります。一方で local ephemeral storage には、別途 `ephemeral-storage` limits、`emptyDir.sizeLimit`、LimitRanges、ResourceQuotas が必要です。また、in-place resize request の後は、Pod spec の desired resources と `status.containerStatuses[].resources` を比較してください。resize が失敗または保留になると、`spec` には要求値が残る一方で、kubelet は以前の runtime allocation を維持し、`PodResizePending` condition を報告することがあります。 -cluster レベルでは、可能な場合は [Pod Security Admission](https://kubernetes.io/docs/concepts/security/pod-security-admission/) の namespace labels を使って Kubernetes の [Pod Security Standards](https://kubernetes.io/docs/concepts/security/pod-security-standards/) を強制します。対応可能な namespace では `restricted` を使い、通常の application namespaces では少なくとも `baseline` を使い、privileged の例外は限定的かつ文書化し、信頼できる platform namespaces または node pools にのみ分離してください。 +多くの application workloads では、non-root UID で実行し、`runAsNonRoot: true` を設定し、`allowPrivilegeEscalation: false` を設定し、すべての capabilities を削除して必要最小限だけ追加し、`seccompProfile: RuntimeDefault` を使い、read-only root filesystem を優先し、host namespaces、hostPath mounts、privileged mode は避けるのが良い基本です。 + +cluster level では、可能な場合は [Pod Security Admission](https://kubernetes.io/docs/concepts/security/pod-security-admission/) の namespace labels を使って Kubernetes の [Pod Security Standards](https://kubernetes.io/docs/concepts/security/pod-security-standards/) を強制してください。対応できる namespace には `restricted` を使い、通常の application namespace には少なくとも `baseline` を使い、privileged の例外は限定的にし、文書化し、信頼できる platform namespace または node pool に隔離してください。 ## References - [https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core) - [https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core) - [https://kubernetes.io/docs/tasks/configure-pod-container/security-context/](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/) +- [https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/) - [https://kubernetes.io/docs/concepts/security/linux-kernel-security-constraints/](https://kubernetes.io/docs/concepts/security/linux-kernel-security-constraints/) - [https://kubernetes.io/docs/concepts/security/pod-security-standards/](https://kubernetes.io/docs/concepts/security/pod-security-standards/) - [https://kubernetes.io/docs/concepts/security/pod-security-admission/](https://kubernetes.io/docs/concepts/security/pod-security-admission/) +- [https://kubernetes.io/docs/tasks/configure-pod-container/assign-pod-level-resources/](https://kubernetes.io/docs/tasks/configure-pod-container/assign-pod-level-resources/) +- [https://kubernetes.io/docs/tasks/configure-pod-container/resize-container-resources/](https://kubernetes.io/docs/tasks/configure-pod-container/resize-container-resources/) {{#include ../../../banners/hacktricks-training.md}}