記事ディレクトリ
1. セキュリティの仕組み
分散クラスターの管理ツールである Kubernetes は、クラスターのセキュリティを確保するための重要なタスクです。API サーバーは、クラスター内のさまざまなコンポーネント間の通信の仲介であり、外部制御の入り口でもあります。したがって、Kubernetes のセキュリティ メカニズムは、基本的に API サーバーを保護するように設計されています。
API サーバーは k8s クラスターの入り口であり、デフォルトで 2 つのポートがあります。
- ローカル ポート 8080: HTTP リクエストの受信に使用されます。外部サービスはありません。認証されていない、または承認されていない HTTP リクエストは、このポートを介して API サーバーにアクセスします。
- セキュア ポート 6443: 認証と承認のための HTTPS 要求を受信し、外部サービスを提供するために使用されます。
ユーザーは、セキュア ポートを介して k8s API サーバーにアクセスするために、認証、承認、およびアクセス制御の 3 つのレベルを通過する必要があります。
- 認証 認証: ユーザー ID の識別に使用
- 承認承認: リソースに関連する権限があるかどうかを確認します
- アドミッション コントロール: 操作がクラスターの要件を満たしているかどうかを判断します。
2. 認証
2.1 認証方法
-
HTTP トークン認証: トークンを使用して正当なユーザーを識別します
.HTTP トークン認証は、特別な方法でエンコードされた非常に長いトークン文字列で顧客を表現する方法であり、模倣することは困難です. トークンは非常に長く複雑な文字列であり、各トークンはユーザー名に対応し、API サーバーがアクセスできるファイルに格納されます。クライアントが API 呼び出し要求を開始するとき、トークンを HTTP ヘッダーに入れる必要があります。 -
HTTP ベース認証: ユーザー名とパスワードを使用してユーザー名とパスワードを認証します
. BASE64 アルゴリズムによってエンコードされた文字列は、HTTP 要求の Heather Authorization フィールドに配置され、サーバーに送信されます. それを受信した後、サーバーはそれをデコードし、ユーザー名とパスワードを取得します。 -
HTTPS 証明書認証(最も厳格): CA ルート証明書の署名に基づくクライアント ID 認証方法。
注: トークン認証とベース認証は、サーバーからクライアントへの認証にのみ使用できます一方向認証、およびクライアントはサーバーが合法であるかどうかを知りません; HTTPS証明書認証方法は実現できます双方向認証。
- 認証が必要なアクセスの種類:
- API サーバーへの Kubernetes コンポーネントのアクセス: kubectl、kubelet、kube-proxy
- Kubernetes が管理する Pod が API サーバーにアクセス: Pod (coredns、dashborad も Pod として実行)
- セキュリティ上の注意:
- Controller Manager、Scheduler、API Server は同じマシン上にあるため、API Server の非セキュア ポート アクセス (ポート 8080 など) を直接使用します。
- kubectl、kubelet、および kube-proxy が API サーバーにアクセスする場合、HTTPS 双方向認証には証明書が必要で、ポート番号は 6443 です。
- 発行された証明書:
- 手動発行: バイナリ展開を使用する場合、CA で HTTPS 証明書を手動で発行する必要があります。
- 自動発行: kubelet が初めて API サーバーにアクセスするとき、トークンは認証に使用されます. 通過後、Controller Manager は kubelet の証明書を生成し、以降のアクセスはすべて証明書で認証されます.
- kubeconfig
kubeconfig ファイルには、クラスター パラメーター (CA 証明書、API サーバー アドレス)、クライアント パラメーター (上で生成された証明書と秘密鍵)、クラスター コンテキスト パラメーター (クラスター名、ユーザー名) が含まれます。Kubenetes コンポーネント (kubelet、kube-proxy など) は、起動時に別の kubeconfig ファイルを指定することで、別のクラスターに切り替えて apiserver に接続できます。
つまり、kubeconfig ファイルは、クラスターの記述であるだけでなく、クラスター認証情報を埋めるものでもあります。クラスターのアクセス方法と認証情報が含まれます。デフォルトでは、kubectl ファイルは ~/.kube/config にあります。 - サービス アカウント
サービス アカウントは、Pod 内のコンテナーが API サーバーにアクセスできるようにするためのものです。Pod は動的に作成および破棄されるため、Pod ごとに手動で証明書を生成することはできません。Kubenetes は Service Account を使用して認証をリサイクルし、Pod が API サーバーにアクセスする際の認証問題を解決します。 - Secret と SA の関係により、
Kubernetes は Secret と呼ばれるリソース オブジェクトを設計しました。これは次の 2 つのカテゴリに分類されます。
- ServiceAccount の保存に使用されるサービス アカウント トークン
- ユーザー定義の機密情報を保存するための不透明
2.2 サービスアカウント(SA)
サービス アカウントには 3 つの部分があります。
- トークン: API サーバーにアクセスする際のサーバー側認証に使用される、API サーバーの秘密鍵で署名されたトークン文字列のシリアル番号です。
- ca.crt: API サーバーから送信された証明書を検証するためにクライアントが使用する CA ルート証明書
- namespace: このサービス アカウント トークンのロール ドメインの名前空間を特定します
デフォルトでは、各名前空間にはサービス アカウントがあります。Pod の作成時にサービス アカウントが指定されていない場合、Pod が属する名前空間のサービス アカウントが使用されます。各ポッドは、作成後に自動的に spec.serviceAccount をデフォルトに設定します (別のサービス アカウントが指定されていない場合)。
kubectl get sa -A
各 Pod が開始されると、ServiceAccount のトークン、ca.crt、名前空間が /var/run/secrets/kubernetes.io/serviceaccount/ にマウントされます。
kubectl get pod -n kube-system
kubectl exec -it kube-proxy-556vt -n kube-system sh
3. 認可
認証 (Authentication) プロセスは、通信の両当事者が、相手が信頼できるものであり、相互に通信できることを確認したことを確認するだけです。一方、認証は、リクエスタが所有するリソースを決定する権限です。
API サーバーは現在、次の承認戦略をサポートしています。
- AlwaysDeny : すべてのリクエストが拒否されることを示し、通常はテストに使用されます
- AlwaysAllow : All requests are allowed to be received. クラスターが承認プロセスを必要としない場合、この戦略を使用でき、通常はテストに使用されます
- ABAC (属性ベースのアクセス制御): 属性ベースのアクセス制御とは、ユーザーが構成した承認規則を使用して、ユーザー要求を照合および制御することを意味します。つまり、アクセスタイプの属性を定義すると、ユーザーはこの属性を使用して対応するリソースにアクセスできます。この設定方法はより面倒で、各設定で属性の長いリストを定義する必要があります。
- Webhook : 外部 REST サービスを呼び出してユーザーを承認することで、K8S をクラスター外で認証できます。
- RBAC(役割ベースのアクセス制御):役割ベースのアクセス制御、K8S はバージョン 1.6 以降、デフォルトでルールを使用します
3.1 RBAC
- 他のアクセス制御方法と比較して、RBAC には次の利点があります。
- クラスター内のリソース (Pod、Deployment、Service) および非リソース (メタ情報またはリソース ステータス) の完全なカバレッジ
- RBAC全体は、いくつかのAPIリソースオブジェクトによって完全に完成されています.他のAPIリソースオブジェクトと同様に、kubectlまたはAPIで操作できます.
- API サーバーを再起動せずに実行時に調整できますが、ABAC では API サーバーを再起動する必要があります。
- RBAC の API リソース オブジェクトの説明
RBAC は、4 つの新しい最上位リソース オブジェクトを導入します: Role、ClusterRole、RoleBinding、および ClusterRoleBinding . 4 つのオブジェクト タイプはすべて、kubectl および API サーバーによって操作できます。
公式ドキュメント: https://kubernetes.io/docs/reference/access-authn-authz/rbac/
-
Role
: 指定された名前空間のリソース制御権限を認可
ClusterRole: すべての名前空間のリソース制御権限を認可
RoleBinding を使用して ClusterRole をバインドする場合は、名前空間の影響を受けますが、ClusterRoleBinding を使用して ClusterRole をバインドする場合は、 K8S クラスター全体。 -
役割バインディング
RoleBinding: 役割をサブジェクト (つまり、サブジェクト) にバインドします。
ClusterRoleBinding: クラスタ ロールをサブジェクトにバインドします。 -
Subject (サブジェクト)
User: ユーザー
Group: ユーザーグループ
ServiceAccount: サービスアカウント
ユーザーは文字列で表され、そのプレフィックス system: はシステムによって予約されています. クラスタ管理者は、通常のユーザーがこのプレフィックス形式を使用しないことを確認する必要があります. グループの書き込み形式はユーザーと同じであり、システム
:プレフィックスもシステム用に予約されています。
Pod が ServiceAccount 認証を使用する場合、service-account-token の JWT はユーザー情報を保存します。ユーザー情報を使用して、ロール/ロール バインディング (クラスター ロール/クラスター ロール バインディング) リソース オブジェクトのペアを作成し、パーミッション バインディングを完了します。
- Role と ClusterRole
RBAC API では、Role はルールの権限のセットを表します. 権限は増やすことしかできません (累積的な権限). 最初にリソースが多くの権限を持ち、RBAC によって削減されるという操作はありません. つまり、ホワイトリストの許可のみがあり、ブラックリストの許可の概念はありません。
概要:
Role は 1 つの namespace でのみ定義できます. 複数の名前空間を使用する場合は、ClusterRole を作成できます。つまり、名前空間をバインドして ClusterRole を定義する必要はありません。
3.2 例
- 役割の例:
apiVersion: rbac.authorization.k8s.io/v1 #指定 core API 组和版本
kind: Role #指定类型为 Role
metadata:
namespace: default #使用默认命名空间
name: pod-reader #Role 的名称
rules: #定义规则
- apiGroups: [""] #""表示 apiGroups 和 apiVersion 使用相同的 core API 组,即 rbac.authorization.k8s.io
resources: ["pods"] #资源对象为 Pod 类型
verbs: ["get", "watch", "list"] #被授予的操作权限
pod-reader の役割をユーザーに割り当てると、このユーザーは、デフォルトの名前空間の Pod リソース オブジェクトに対する 3 つの操作権限を持ちます: get (取得)、watch (監視)、および list (リスト)。
- ClusterRole の例:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
# "namespace" 被忽略,因为 ClusterRoles 不受名称空间限制
name: secret-reader
rules:
- apiGroups: [""]
resources: ["secrets"] #资源对象为 Secret 类型
verbs: ["get", "watch", "list"]
Cluseterole は名前空間の影響を受けず、すべての名前空間に作用するため、名前空間を指定する必要はありません
- RoleBinding の例
- 参照ロール ロール バインディング
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods
namespace: default
subjects:
- kind: User
name: zhangsan
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
zhangsan ユーザーにデフォルトの名前空間の pod-reader Role を付与すると、zhangsan ユーザーはデフォルトの名前空間で pod-reader 権限を持つようになります。
- Using ClusterRole role binding
RoleBinding can also refer to ClusterRole to authorize User, Group or ServiceAccount in the current namespace. この操作により、クラスター管理者はクラスター全体でいくつかの一般的な ClusterRole を定義し、RoleBinding を使用して別の名前空間でそれらを参照できます。
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-secrets
namespace: kube-public
subjects:
- kind: User
name: lisi
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: secret-reader
apiGroup: rbac.authorization.k8s.io
注: RoleBinding バインディングは名前空間によって制限されるため、ClusterRole ロールに名前空間のアクセス許可がある場合でも、RoleBingding によって設定された名前空間に制限されるため、上記の lisi ユーザーは、で使用される kube-public スペース内のシークレットにのみアクセスできます
。
- ClusterRoleBinding の例:
ClusterRoleBinding を使用して、クラスター全体のすべての名前空間リソースのアクセス許可を承認する
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: read-secrets-global
subjects:
- kind: Group
name: manager
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: secret-reader
apiGroup: rbac.authorization.k8s.io
ClusterRoleBinding は、マネージャー グループ内のすべてのユーザーに、すべての名前空間内のシークレットへのアクセスを許可します。
3.3 リソース
Kubernetes クラスター内の一部のリソースは通常、名前の文字列で表され、これらの文字列は通常 API の URL アドレスに表示されます。同時に、ログ リソースがサブリソースであるなど、一部のリソースにはサブリソースも含まれます。 Pod ログのサンプル リクエスト URL は次のとおりです:
GET /api/v1/namespaces/{namespace}/pods/{name}/log
RBAC 承認モデルでこれらのサブリソースのアクセス権を制御するために、リソースとサブリソースを / セパレーターで区切ることができます。
例:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: pod-and-pod-logs-reader
rules:
- apiGroups: [""]
resources: ["pods", "pods/log"]
verbs: ["get", "list"]
ルールのリソース定義には、次のタイプがあります。
- rules.verbs有:「get」、「list」、「watch」、「create」、「update」、「patch」、「delete」、「exec」
- rules.resources有:「services」、「endpoints」、「pods」、「secrets」、「configmaps」、「crontabs」、「deployments」、「jobs」、「nodes」、「rolebindings」、「clusterroles」、「 daemonsets」、「replicasets」、「statefulsets」、「horizontalpodautoscalers」、「replicationcontrollers」、「cronjobs」
- rules.apiGroups有:「」、「apps」、「autoscaling」、「batch」
4. 入場管理
認証と認証に合格した後、クライアントは API サーバーから実際の応答を取得できません。この要求は、アドミッション コントロールによって制御されるアドミッション コントロール プラグイン リストのレイヤーごとのテストに合格する必要があります。
アドミッション コントロールには、「アドミッション コントローラー」のプラグイン リストが装備されています. API サーバーに送信されるすべてのリクエストは、リスト内の各アドミッション コントローラーのチェックに合格する必要があり、チェックが失敗した場合、呼び出し要求は API サーバーによって拒否されます。不通過。
さらに、アドミッション コントローラはリクエスト パラメータを変更して、サービス アカウント コントローラなどの自動化されたタスクを完了することもできます。
現在設定可能なアドミッション コントロールは次のとおりです。
- AlwaysAdmit: すべての要求を許可します。
- AlwaysPullimages: コンテナーを開始する前に常にイメージをダウンロードします。これは、構成項目 imagePullPolicy=Always で各コンテナーと同等です。
- AlwaysDeny: すべてのリクエストを禁止します。通常はテストに使用されます。
- DenyExecOnPrivileged: 特権コンテナーでコマンドを実行するすべての要求をインターセプトします. クラスターが特権コンテナーをサポートしていて、ユーザーがこれらの特権コンテナーでコマンドを実行するのを制限したい場合は、それを使用することを強くお勧めします. その機能は DenyEscalatingExec にマージされました.
- ImagePolicyWebhook: このプラグインは、バックエンドの Webhook プログラムがアドミッション コントローラーの機能を実行できるようにします。ImagePolicyWebhook は、バックエンド Webhook のパラメーターを定義するために、構成ファイル (kube-apiserver スタートアップ パラメーター – Admission-Control-config-file で設定) を使用する必要があります。プラグインは現在アルファ版です。
- サービス アカウント: このプラグインは ServiceAccount を自動化し、デフォルトで有効になっています. ServiceAccount オブジェクトを使用する場合は、それを使用することを強くお勧めします.
- SecurityContextDeny: このプラグインは、SecurityContext を使用してポッド内のすべての定義を無効にします。SecurityContext は、コンテナ内のオペレーティング システム レベルのセキュリティ設定 (uid、gid、capabilityes、SELinux など) を定義します。PodSecurityPolicy が有効になっていないクラスターでは、コンテナー設定への非セキュアなアクセスを無効にするために、このプラグインを有効にすることをお勧めします。
- ResourceQuota: リソース クォータ管理の目的で使用され、名前空間に作用し、すべての要求を監視して、名前空間のクォータが標準を超えないようにします。このプラグインをアドミッション コントロール パラメータ リストの最後に配置することをお勧めします。これにより、他のプラグインによって拒否される可能性がある Pod へのリソースの早すぎる割り当てを避けることができます。
- LimitRanger: リソース制限管理に使用され、名前空間に作用して Pod のリソースが制限されていることを確認します。このプラグインを有効にすると、リソース制限が設定されていない Pod のデフォルト設定も設定されます。たとえば、名前空間「default」のすべての Pod に 0.1CPU のリソース リクエストが設定されます。
- InitialResources: ミラー化された履歴リソースの使用状況に基づいて、リソース リクエストと制限を設定していない Pod のリソース リクエストと制限設定を初期化するように設計された実験的な機能です。
- NamespaceLifecycle: 存在しない名前空間でリソース オブジェクトを作成しようとすると、作成要求は拒否されます。名前空間を削除すると、システムは名前空間内のすべてのオブジェクトを削除し、ポッド、サービスなどを保存します。
- DefaultStorageClass: 共有ストレージの動的プロビジョニングを実現するために、StorageClass または PV を指定しない PVC のデフォルトの StorageClass を一致させ、PVC を申請するときにユーザーが知る必要があるバックエンド ストレージの詳細を最小限に抑えます。
- DefaultTolerationSeconds: このプラグインは、許しの容認を設定せず、notready:NoExecute と unreachable:NoExecute の 2 つのテイントを持つ Pod のデフォルトの「許容」時間を 5 分に設定します。
- PodSecurityPolicy: このプラグインは、Pod の作成または変更時に Pod のセキュリティ コンテキストと利用可能な PodSecurityPolicy に基づいて Pod のセキュリティ ポリシーを制御するかどうかを決定するために使用されます。
5. ServiceAccount アクセスケース
5.1 名前空間を作成する
kubectl create namespace sa
名前空間を作成すると、デフォルトでサービス アカウントとシークレットが作成されます
#查看sa名称空间的sa证书
kubectl get sa -n sa
#查看sa名称空间的secret
kubectl get secret -n sa
#查看sa证书
kubectl describe sa default -n sa
#查看token
kubectl describe secret default-token-4mp4g -n sa
5.2 ポッドを作成してその sa とシークレットを検証する
#创建一个pod
kubectl run nginx --image=nginx:1.15 -n sa
#查看pod详细信息
kubectl get pod nginx -n sa -o yaml |grep serviceAccount
serviceaccount を指定せずに Pod を作成し、デフォルトで default を使用する
5.3 sa の作成
#在sn名称空间中创建一个sa
kubectl create sa daniel -n sa
#查询sa
kubectl get sa -n sa
#查询secret
kubectl get secret -n sa
5.4 Pod の作成と sa のカスタマイズ
vim sa-pod.yml
apiVersion: v1
kind: Pod
metadata:
name: nginx2
namespace: sa
spec:
containers:
- name: c1
image: nginx:1.15-alpine
ports:
- name: httpd
containerPort: 80
serviceAccountName: daniel # 指定sa为daniel
ポッドを作成する
kubectl apply -f sa-pod.yml
#查看pod的sa
kubectl get pod nginx2 -n sa -o yaml |grep serviceAccount