|
| 1 | +--- |
| 2 | +layout: blog |
| 3 | +title: 'Kubernetes 1.31: Fine-grained SupplementalGroups control' |
| 4 | +date: 2024-08-22 |
| 5 | +slug: fine-grained-supplementalgroups-control |
| 6 | +author: > |
| 7 | + Shingo Omura (Woven By Toyota) |
| 8 | +
|
| 9 | +--- |
| 10 | + |
| 11 | +この記事ではKubernetes 1.31の新機能である、Pod内のコンテナにおける補助グループ制御の改善機能について説明します。 |
| 12 | + |
| 13 | +## 動機: コンテナイメージ内の`/etc/group`に定義される暗黙的なグループ情報 |
| 14 | + |
| 15 | +この挙動は多くのKubernetesユーザー、管理者にとってあまり知られていないかもしれませんが、Kubernetesは、デフォルトでは、Podで定義された情報に加えて、コンテナイメージ内の`/etc/group`のグループ情報を _マージ_ します。 |
| 16 | + |
| 17 | +例を見てみましょう。このPodはsecurity contextで`runAsUser=1000`、`runAsGroup=3000`、`supplementalGroups=4000`を指定しています。 |
| 18 | + |
| 19 | +{{% code_sample file="implicit-groups.yaml" %}} |
| 20 | + |
| 21 | +`ctr`コンテナで`id`コマンドを実行すると何が出力されるでしょうか? |
| 22 | + |
| 23 | +```console |
| 24 | +# Podを作成してみましょう。 |
| 25 | +$ kubectl apply -f https://k8s.io/blog/2024-08-22-Fine-grained-SupplementalGroups-control/implicit-groups.yaml |
| 26 | + |
| 27 | +# Podのコンテナが実行されていることを確認します。 |
| 28 | +$ kubectl get pod implicit-groups |
| 29 | + |
| 30 | +# プロセスのユーザー、グループ情報を確認します。 |
| 31 | +$ kubectl exec implicit-groups -- id |
| 32 | +``` |
| 33 | + |
| 34 | +出力は次のようになるでしょう。 |
| 35 | + |
| 36 | +```none |
| 37 | +uid=1000 gid=3000 groups=3000,4000,50000 |
| 38 | +``` |
| 39 | + |
| 40 | +Podマニフェストには`50000`は一切定義されていないにもかかわらず、補助グループ(`groups`フィールド)に含まれているグループID `50000`は一体どこから来るのでしょうか? 答えはコンテナイメージの`/etc/group`ファイルです。 |
| 41 | + |
| 42 | +コンテナイメージの`/etc/group`の内容が下記のようになっていることが確認できるでしょう。 |
| 43 | + |
| 44 | +```console |
| 45 | +$ kubectl exec implicit-groups -- cat /etc/group |
| 46 | +... |
| 47 | +user-defined-in-image:x:1000: |
| 48 | +group-defined-in-image:x:50000:user-defined-in-image |
| 49 | +``` |
| 50 | + |
| 51 | +なるほど!コンテナのプライマリユーザーであるユーザー(`1000`)がグループ(`50000`)に属していることが最後のエントリから確認出来ました。 |
| 52 | + |
| 53 | +このように、コンテナイメージ上の`/etc/group`で定義される、コンテナのプライマリユーザーのグループ情報は、Podからの情報に加えて _暗黙的にマージ_ されます。ただし、この挙動は、現在のCRI実装がDockerから引き継いだ設計上の決定であり、コミュニティはこれまでこの挙動について再検討することはほとんどありませんでした。 |
| 54 | + |
| 55 | +### 何が悪いのか? |
| 56 | + |
| 57 | +コンテナイメージの`/etc/group`から _暗黙的にマージ_ されるグループ情報は、特にボリュームアクセスを行う際に、セキュリティ上の懸念を引き起こすことがあります(詳細は[kubernetes/kubernetes#112879](https://issue.k8s.io/112879)を参照してください)。なぜなら、Linuxにおいて、ファイルパーミッションはuid/gidで制御されているからです。更に悪いことに、`/etc/group`に由来する暗黙的なgidは、マニフェストに情報が無いため、ポリシーエンジン等でチェック・検知をすることが出来ません。これはKubernetesセキュリティの観点からも懸念となります。 |
| 58 | + |
| 59 | +## PodにおけるFine-grined(きめ細かい) SupplementalGroups control: `SupplementaryGroupsPolicy` |
| 60 | + |
| 61 | +この課題を解決するために、Kubernetes 1.31はPodの`.spec.securityContext`に、新しく`supplementalGroupsPolicy`フィールドを追加します。 |
| 62 | + |
| 63 | +このフィールドは、Pod内のコンテナプロセスに付与される補助グループを決定するを方法を制御できるようにします。有効なポリシーは次の2つです。 |
| 64 | + |
| 65 | +* _Merge_: `/etc/group`で定義されている、コンテナのプライマリユーザーが所属するグループをマージします。指定されていない場合、このポリシーがデフォルトです(後方互換性を考慮して既存の挙動と同様)。 |
| 66 | + |
| 67 | +* _Strict_: `fsGroup`、`supplementalGroups`、`runAsGroup`フィールドで指定されたグループのみ補助グループに指定されます。つまり、`/etc/group`で定義された、コンテナのプライマリユーザーのグループ情報はマージされません。 |
| 68 | + |
| 69 | +では、どのように`Strict`ポリシーが動作するか見てみましょう。 |
| 70 | + |
| 71 | +{{% code_sample file="strict-supplementalgroups-policy.yaml" %}} |
| 72 | + |
| 73 | +```console |
| 74 | +# Podを作成してみましょう。 |
| 75 | +$ kubectl apply -f https://k8s.io/blog/2024-08-22-Fine-grained-SupplementalGroups-control/strict-supplementalgroups-policy.yaml |
| 76 | + |
| 77 | +# Podのコンテナが実行されていることを確認します。 |
| 78 | +$ kubectl get pod strict-supplementalgroups-policy |
| 79 | + |
| 80 | +# プロセスのユーザー、グループ情報を確認します。 |
| 81 | +kubectl exec -it strict-supplementalgroups-policy -- id |
| 82 | +``` |
| 83 | + |
| 84 | +出力はこのようになります。 |
| 85 | + |
| 86 | +```none |
| 87 | +uid=1000 gid=3000 groups=3000,4000 |
| 88 | +``` |
| 89 | + |
| 90 | +`Strict`ポリシーによってグループ`50000`が`groups`から除外されているのが確認できました! |
| 91 | + |
| 92 | +このように、確実に`supplementalGroupsPolicy: Strict`が設定する(ポリシーエンジン等によって強制する)ことで、暗黙的な補助グループを回避することが可能になります。 |
| 93 | + |
| 94 | +{{<note>}} |
| 95 | +このフィールドの値を強制するだけでは不十分な場合もあります。なぜなら、プロセスが自分自身のユーザー、グループ情報を変更できる権限/ケーパビリティを持っている場合があるからです。詳細は次のセクションを参照してください。 |
| 96 | +{{</note>}} |
| 97 | + |
| 98 | +## Podステータスにおける付与されたユーザー、グループ情報の確認 |
| 99 | + |
| 100 | +この機能は、Podの`status.containerStatuses[].user.linux`フィールドでコンテナの最初のプロセスに付与されたユーザー、グループ情報を公開しています。暗黙的なグループIDが付与されているかどうかを確認するのに便利でしょう。 |
| 101 | + |
| 102 | +```yaml |
| 103 | +... |
| 104 | +status: |
| 105 | + containerStatuses: |
| 106 | + - name: ctr |
| 107 | + user: |
| 108 | + linux: |
| 109 | + gid: 3000 |
| 110 | + supplementalGroups: |
| 111 | + - 3000 |
| 112 | + - 4000 |
| 113 | + uid: 1000 |
| 114 | +... |
| 115 | +``` |
| 116 | + |
| 117 | +{{<note>}} |
| 118 | +`status.containerStatuses[].user.linux`フィールドで公開されているユーザー、グループ情報は、コンテナの最初のプロセスに、_最初に付与された_ 情報であることに注意してください。 |
| 119 | +もしそのプロセスが、自身のユーザー、グループ情報を変更できるシステムコール(例えば [`setuid(2)`](https://man7.org/linux/man-pages/man2/setuid.2.html), |
| 120 | +[`setgid(2)`](https://man7.org/linux/man-pages/man2/setgid.2.html), |
| 121 | +[`setgroups(2)`](https://man7.org/linux/man-pages/man2/setgroups.2.html)等)を実行する権限を持っている場合、プロセス自身で動的に変更が可能なためです。 |
| 122 | +つまり、実際にプロセスに付与されているユーザー、グループ情報は動的に変化します。 |
| 123 | +{{</note>}} |
| 124 | + |
| 125 | +## この機能を利用するには |
| 126 | + |
| 127 | +`supplementalGroupsPolicy`フィールドを有効化するには、下記のコンポーネントを利用する必要があります。 |
| 128 | + |
| 129 | +- Kubernetes: v1.31以降、かつ、`SupplementalGroupsPolicy`[フィーチャーゲート](/docs/reference/command-line-tools-reference/feature-gates/)が有効化されていること。v1.31現在、このフィーチャーゲートはAlphaです。 |
| 130 | +- CRI実装: |
| 131 | + - containerd: v2.0以降 |
| 132 | + - CRI-O: v1.31以降 |
| 133 | + |
| 134 | +ノードのステータスでこの機能が利用可能かどうか確認出来ます。 |
| 135 | + |
| 136 | +```yaml |
| 137 | +apiVersion: v1 |
| 138 | +kind: Node |
| 139 | +... |
| 140 | +status: |
| 141 | + features: |
| 142 | + supplementalGroupsPolicy: true |
| 143 | +``` |
| 144 | +
|
| 145 | +## 将来の展望 |
| 146 | +
|
| 147 | +Kubernetes SIG Nodeは、この機能が将来的なKubernetesのリリースでベータ版に昇格し、最終的には一般提供(GA)されることを望んでおり、期待しています。そうなれば、ユーザーはもはや機能ゲートを手動で有効にする必要がなくなります。 |
| 148 | +
|
| 149 | +`supplementalGroupsPolicy`が指定されていない場合は、後方互換性のために`Merge`ポリシーが適用されます。 |
| 150 | + |
| 151 | +## より学ぶには? |
| 152 | + |
| 153 | +<!-- https://github.com/kubernetes/website/pull/46920 --> |
| 154 | + |
| 155 | +`supplementalGroupsPolicy`の詳細については、[ドキュメント](/ja/docs/tasks/configure-pod-container/security-context/)を参照してください。 |
| 156 | + |
| 157 | +## 参加するには? |
| 158 | + |
| 159 | +この機能はSIG Nodeコミュニティによって推進されています。コミュニティに参加して、上記の機能やそれ以外のアイデアやフィードバックを共有してください。皆さんからのご意見をお待ちしています! |
0 commit comments