kubeadm環境のKubernetesにてユーザーを追加
kubeadmにて作成したKubernntes Clusterに、Normal Userを追加する方法を確認します。
環境
- kubernetes
- v1.20.0
実際の追加作業を実施する前に、Kubernetesにおける認証方式やユーザーの扱いについて確認しておきます。
Kubernetesにおける認証方式
kube-apiと認証をするに、様々な方法が用意されています。
Kubernetes uses client certificates, bearer tokens, an authenticating proxy, or HTTP basic auth to authenticate API requests through authentication plugins.
なお、kubeadmにて作成された環境では、client certificatesによる認証が有効になっています。以下は公式ドキュメントの説明ですが、
Client certificate authentication is enabled by passing the --client-ca-file=SOMEFILE option to API server. The referenced file must contain one or more certificate authorities to use to validate client certificates presented to the API server.
実際にkube-apiのpodを確認すると、起動時に --client-ca-file
というオプションが付与されています。
$ kubectl -n kube-system describe pod kube-apiserver-kubeadm-master | grep -iA10 command Command: kube-apiserver --advertise-address=10.146.0.2 --allow-privileged=true --authorization-mode=Node,RBAC --client-ca-file=/etc/kubernetes/pki/ca.crt # <-ここ --enable-admission-plugins=NodeRestriction --enable-bootstrap-token-auth=true --etcd-cafile=/etc/kubernetes/pki/etcd/ca.crt --etcd-certfile=/etc/kubernetes/pki/apiserver-etcd-client.crt --etcd-keyfile=/etc/kubernetes/pki/apiserver-etcd-client.key
kubeadmによるCluster初期化時に作成された認証局を、kube-api側に登録してくれています。
Kubernetesにおけるユーザーとは
公式ドキュメントでの説明。
All Kubernetes clusters have two categories of users: service accounts managed by Kubernetes, and normal users.
It is assumed that a cluster-independent service manages normal users in the following ways:
・an administrator distributing private keys
・a user store like Keystone or Google Accounts
・a file with a list of usernames and passwords
In this regard, Kubernetes does not have objects which represent normal user accounts. Normal users cannot be added to a cluster through an API call.
Even though a normal user cannot be added via an API call, any user that presents a valid certificate signed by the cluster's certificate authority (CA) is considered authenticated. In this configuration, Kubernetes determines the username from the common name field in the 'subject' of the cert (e.g., "/CN=bob"). From there, the role based access control (RBAC) sub-system would determine whether the user is authorized to perform a specific operation on a resource.
ユーザーというオブジェクトは存在しないものの、Kuberrnetes Cluster内の認証局にて署名された証明書をもつユーザーであれば認証するよ、という話でしょうか。
Kuberrnetes Cluster内の認証局とは、つまり上記でkube-api起動時に登録した認証局となる訳ですが、Kubernetesでは、この認証局で証明書を発行してくれる機能をAPIにて提供しています。 kind: CertificateSigningRequest
というオブジェクトにCSR情報を含めて登録することで、証明書を発行してくれます。この発行された証明書をクライアント証明書として、kubectlのkubeconfigに設定することで、kube-apiとユーザー認証できるようなります。
ユーザーの追加
実際にユーザーを追加してみます。以下の公式ドキュメントに沿って作業。
CSRファイルの作成
まず、Kubernetesに登録するためのCSRファイルを作成します。
秘密鍵の作成。
$ openssl genrsa -out zunko.key 2048 Generating RSA private key, 2048 bit long modulus (2 primes) ..................+++++ ......................................+++++ e is 65537 (0x010001)
作成した秘密鍵をもとにCSRファイルを作成します。CN(Common Name)がユーザー名、O(Organization Name)がグループ名として利用されるとの事。
It is important to set CN and O attribute of the CSR. CN is the name of the user and O is the group that this user will belong to.
コモンネームを zunko
として、CSRファイルを作成します。
$ openssl req -new -key zunko.key -out zunko.csr You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]: State or Province Name (full name) [Some-State]: Locality Name (eg, city) []: Organization Name (eg, company) [Internet Widgits Pty Ltd]: Organizational Unit Name (eg, section) []: Common Name (e.g. server FQDN or YOUR name) []:zunko Email Address []: Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []:
CSRファイルの登録
CSRを登録するにはBase64文字列としてする必要あるため、CSRファイルのBase64エンコードした文字列を取得します。
$ cat zunko.csr | base64 | tr -d "\n" LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ21qQ0NBWUlDQVFBd1ZURUxNQWtHQTFVRUJoTUNRVlV4RXpBUkJnTlZCQWdNQ2xOdmJXVXRVM1JoZEdVeApJVEFmQmdOVkJBb01HRWx1ZEdWeWJtVjBJRmRwWkdkcGRITWdVSFI1SUV4MFpERU9NQXdHQTFVRUF3d0ZlblZ1CmEyOHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFEQ2lEcHU3MFdpSTZwYkttekIKdlhyZUVPRy8yTXNHa0lVZ3NseGJvMmV1cy9QUllPb0gyZU1INkNOWTNMMmVsS1hueDBZcEQyT2I2QURpeVR5cQpQZEhzNnFXQVRabHJtRjZBcmJWaS8vU3BMWUNmR2ptSkp3VWVzN3k3VXBnZ2QwSE1LeWtyNFY1L2FzYlV5dVlOCklBRjhiN0ptbTRWZ3ovd1RMMzIvTDFEOVRNUXJLZ0FYNkFUMTdUZENrdEh2OW1nWXNMRDhQdDd6b0VZNnZnNDUKNTUwaWZRZ1V5blR3MjRCcjJzOXRValgxRjZtb1dHdjY2TmxuQmpqaVdKek1hQzlMWVVjUVhMU2htMEx6ekpLdwo3SHY5aWFNL0Ixcjc2Q3VBNEhuaFdZRlJRbDNIZEVqSzVGcUllUi8xOUVDb2ZFK2FObmplV2k4S1NmeEpIK0xLCjdMMFpBZ01CQUFHZ0FEQU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFVTGh1cnM1aWJ0N0VQdmo0R3hNOGFjOFgKTHBLOEg4RWZIVnNUcWJTd2hLL0w1TFNEbFBRaGNNdUlyZDdRL25oR1BvbkJ5SEVDQmFLKzZ3OHVaY0hUNFY0Lwo4Q21MSTAyUm04N1dpTVlmL0F3MFFIcGRWQUJiaTFtam0vanQ1aG1tM001MUYvSldtOG1YN0lkQnEyOW1uVGhzCkxJb3RkYnRIckk3dzZYelRJeGdMN2ZCT0IwM2l2aWd3M01qS29XUXB1SHdSQnBmVkF3b2NMdHR6L3NBbldmakwKYlBGZndVdExkS0VIWHVJOGVhTFo5eCtqVzNVZmNkdTluUUtudTZNUEcvbWh6eEx1aVRNYnZaQzdWcDltOSsvbApLcVltNzFXdVk0TnVXOEpkUGhTOVFEZE9Wc2k3bXRjd0FWZmFtYTlkY2NKUUdiUllwZG15a25tMzZrbnRJZz09Ci0tLS0tRU5EIENFUlRJRklDQVRFIFJFUVVFU1QtLS0tLQo=
取得した文字列をもとに、以下の CertificateSigningRequest
用マニフェストファイルを作成します。
apiVersion: certificates.k8s.io/v1 kind: CertificateSigningRequest metadata: name: zunko spec: groups: - system:authenticated request: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ21qQ0NBWUlDQVFBd1ZURUxNQWtHQTFVRUJoTUNRVlV4RXpBUkJnTlZCQWdNQ2xOdmJXVXRVM1JoZEdVeApJVEFmQmdOVkJBb01HRWx1ZEdWeWJtVjBJRmRwWkdkcGRITWdVSFI1SUV4MFpERU9NQXdHQTFVRUF3d0ZlblZ1CmEyOHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFEQ2lEcHU3MFdpSTZwYkttekIKdlhyZUVPRy8yTXNHa0lVZ3NseGJvMmV1cy9QUllPb0gyZU1INkNOWTNMMmVsS1hueDBZcEQyT2I2QURpeVR5cQpQZEhzNnFXQVRabHJtRjZBcmJWaS8vU3BMWUNmR2ptSkp3VWVzN3k3VXBnZ2QwSE1LeWtyNFY1L2FzYlV5dVlOCklBRjhiN0ptbTRWZ3ovd1RMMzIvTDFEOVRNUXJLZ0FYNkFUMTdUZENrdEh2OW1nWXNMRDhQdDd6b0VZNnZnNDUKNTUwaWZRZ1V5blR3MjRCcjJzOXRValgxRjZtb1dHdjY2TmxuQmpqaVdKek1hQzlMWVVjUVhMU2htMEx6ekpLdwo3SHY5aWFNL0Ixcjc2Q3VBNEhuaFdZRlJRbDNIZEVqSzVGcUllUi8xOUVDb2ZFK2FObmplV2k4S1NmeEpIK0xLCjdMMFpBZ01CQUFHZ0FEQU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFVTGh1cnM1aWJ0N0VQdmo0R3hNOGFjOFgKTHBLOEg4RWZIVnNUcWJTd2hLL0w1TFNEbFBRaGNNdUlyZDdRL25oR1BvbkJ5SEVDQmFLKzZ3OHVaY0hUNFY0Lwo4Q21MSTAyUm04N1dpTVlmL0F3MFFIcGRWQUJiaTFtam0vanQ1aG1tM001MUYvSldtOG1YN0lkQnEyOW1uVGhzCkxJb3RkYnRIckk3dzZYelRJeGdMN2ZCT0IwM2l2aWd3M01qS29XUXB1SHdSQnBmVkF3b2NMdHR6L3NBbldmakwKYlBGZndVdExkS0VIWHVJOGVhTFo5eCtqVzNVZmNkdTluUUtudTZNUEcvbWh6eEx1aVRNYnZaQzdWcDltOSsvbApLcVltNzFXdVk0TnVXOEpkUGhTOVFEZE9Wc2k3bXRjd0FWZmFtYTlkY2NKUUdiUllwZG15a25tMzZrbnRJZz09Ci0tLS0tRU5EIENFUlRJRklDQVRFIFJFUVVFU1QtLS0tLQo= signerName: kubernetes.io/kube-apiserver-client usages: - client auth
admin権限をもったユーザーにて、作成したマニフェストファイルを登録します。
$ kubectl apply -f csr-zunko.yaml
certificatesigningrequest.certificates.k8s.io/zunko created
CSRの承認
登録されたCSRは Pending
状態となっています。
$ kubectl get csr NAME AGE SIGNERNAME REQUESTOR CONDITION zunko 29s kubernetes.io/kube-apiserver-client kubernetes-admin Pending
approveコマンドを実行することで、証明書を発行可能となります。
$ kubectl certificate approve zunko certificatesigningrequest.certificates.k8s.io/zunko approved
approveされました。
$ kubectl get csr NAME AGE SIGNERNAME REQUESTOR CONDITION zunko 2m39s kubernetes.io/kube-apiserver-client kubernetes-admin Approved,Issued
証明書の取得
発行された証明書は、CSRオブジェクトの .status.certificate
フィールドに記載されています。
$ kubectl get csr zunko -o jsonpath='{.status.certificate}' LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURPekNDQWlPZ0F3SUJBZ0lSQU5Ga3pWek1zbHJPcjZBbU85L1FkdHd3RFFZSktvWklodmNOQVFFTEJRQXcKRlRFVE1CRUdBMVVFQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB5TVRBeE1UWXlNVE0yTlROYUZ3MHlNakF4TVRZeQpNVE0yTlROYU1GVXhDekFKQmdOVkJBWVRBa0ZWTVJNd0VRWURWUVFJRXdwVGIyMWxMVk4wWVhSbE1TRXdId1lEClZRUUtFeGhKYm5SbGNtNWxkQ0JYYVdSbmFYUnpJRkIwZVNCTWRHUXhEakFNQmdOVkJBTVRCWHAxYm10dk1JSUIKSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXdvZzZidTlGb2lPcVd5cHN3YjE2M2hEaAp2OWpMQnBDRklMSmNXNk5ucnJQejBXRHFCOW5qQitnaldOeTlucFNsNThkR0tROWptK2dBNHNrOHFqM1I3T3FsCmdFMlphNWhlZ0syMVl2LzBxUzJBbnhvNWlTY0ZIck84dTFLWUlIZEJ6Q3NwSytGZWYyckcxTXJtRFNBQmZHK3kKWnB1RllNLzhFeTk5dnk5US9VekVLeW9BRitnRTllMDNRcExSNy9ab0dMQ3cvRDdlODZCR09yNE9PZWVkSW4wSQpGTXAwOE51QWE5clBiVkkxOVJlcHFGaHIrdWpaWndZNDRsaWN6R2d2UzJGSEVGeTBvWnRDODh5U3NPeDcvWW1qClB3ZGErK2dyZ09CNTRWbUJVVUpkeDNSSXl1UmFpSGtmOWZSQXFIeFBtalo0M2xvdkNrbjhTUi9peXV5OUdRSUQKQVFBQm8wWXdSREFUQmdOVkhTVUVEREFLQmdnckJnRUZCUWNEQWpBTUJnTlZIUk1CQWY4RUFqQUFNQjhHQTFVZApJd1FZTUJhQUZEMVByTnZCMkhJaXZCQ1pGT3VJL0dCNnQzNzZNQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUUJ6CmpuR1ZIaGNJYkVCbW56NzI1ZlR0RjN2RzJPUktlVFJxa3B4bkdQTHZYUjU1VEMwbVE4TUZRYnozckdNQzZDbmEKd2hhUWNEL2hmMGhadXBGdXdsaXhwamlMbElkRVpUYXIrc2JGc1VwL2JZSnFTVG5UV1E5TDZYWEQzbmVjUGtnbgpvemRnYnZ1bTUwb1JOS1djaHE0eVV4TkhQQkEzcWxnSWM3cXkrdXV1YTVZVnJPNkpIaHVXQkY3ZHdmVEowYU90ClZJbWs5R0FQTDFROGNjVk94YmwxOTc5Q1pKWHY5VzhDTkFXTTd0aVdtQVBCOG92bUkwaDJnTzg2WlY1OUttVzMKS2FYZ2hpUTk4SC9CL3hhRkQ0NDNHKzk0bUxXdWZJdjVhZW42WU95RWZidk1wcENZQkNsVGtwSjM2SHNLUHhqLwpiUkxjb2NmSG9tZHdvN2tmT1ZhUwotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
ファイルに保存しておきます。なお、ファイル保存時にBase64デコードしておきます。
$ kubectl get csr zunko -o jsonpath='{.status.certificate}' | base64 -d > zunko.crt
RBACの設定
追加するzunkoユーザーで利用するRoleとRole Bindingを作成します。
clusterroleを作成。
$ kubectl create clusterrole pod-reader --verb=get,list,watch --resource=pods clusterrole.rbac.authorization.k8s.io/pod-reader created
紐づくclusterrolebindingを作成。
$ kubectl create clusterrolebinding pod-reader_zunko --clusterrole=pod-reader --user=zunko clusterrolebinding.rbac.authorization.k8s.io/pod-reader_zunko created
Cluster側で必要な設定は完了です。
kubeconfigの設定
kubeconfigに必要情報を設定します。
zunkoユーザーを追加します。
$ kubectl config set-credentials zunko --client-key=zunko.key --client-certificate=zunko.crt --embed-certs=true User "zunko" set.
コンテキストを追加します。
$ kubectl config set-context zunko@kubernetes --cluster=kubernetes --user=zunko Context "zunko@kubernetes" created.
確認。
$ kubectl config view apiVersion: v1 clusters: - cluster: certificate-authority-data: DATA+OMITTED server: https://10.146.0.2:6443 name: kubernetes contexts: - context: cluster: kubernetes user: kubernetes-admin name: kubernetes-admin@kubernetes - context: cluster: kubernetes user: zunko name: zunko@kubernetes current-context: kubernetes-admin@kubernetes kind: Config preferences: {} users: - name: kubernetes-admin user: client-certificate-data: REDACTED client-key-data: REDACTED - name: zunko user: client-certificate-data: REDACTED client-key-data: REDACTED
確認
実際にzunkoユーザーでアクセスしてみます。
利用するコンテキストをzunkoユーザーに変更。
$ kubectl config use-context zunko@kubernetes Switched to context "zunko@kubernetes".
確認。
$ kubectl get pod --all-namespaces NAMESPACE NAME READY STATUS RESTARTS AGE default sample-67df9696d9-nmpzx 1/1 Running 2 31h kube-system calico-kube-controllers-744cfdf676-rp98f 1/1 Running 4 33h kube-system calico-node-rldrx 1/1 Running 3 32h kube-system calico-node-xh97n 1/1 Running 4 33h kube-system coredns-74ff55c5b-49hdn 1/1 Running 4 33h kube-system coredns-74ff55c5b-5j9cf 1/1 Running 4 33h kube-system etcd-kubeadm-master 1/1 Running 0 5h42m kube-system kube-apiserver-kubeadm-master 1/1 Running 5 33h kube-system kube-controller-manager-kubeadm-master 1/1 Running 6 33h kube-system kube-proxy-7dhmd 1/1 Running 3 32h kube-system kube-proxy-8v785 1/1 Running 4 33h kube-system kube-scheduler-kubeadm-master 1/1 Running 6 33h $ $ kubectl run sample --image=nginx --restart=Never Error from server (Forbidden): pods is forbidden: User "zunko" cannot create resource "pods" in API group "" in the namespace "default"
上手くいってますね。