前提
今回なんでこんなことをするかという背景として、
社内ツールをkubernetes上で動かしていて、それをあるmasterとは別のサーバにNATすることで、NATサーバのIPからアプリケーションにアクセスできるようにしていたのですが、興味などでkubectlに触れてみたいと思う方もいらっしゃるかなと思いました。
そういう訳で、そのNATサーバーからkubectlを打てるようにしてあげようと思ったのですが、podに変更を加えられたくなかったので、Podの情報だけはを見れるようにしようということで、以下のことをしていくこととなりました。
まず初めに
提供するサーバに、kubernetesを操作するサーバの/root/.kube/configをコピーしておきます。
これで、そのサーバからkubernetesが操作できると思います。
ClusterRoleの準備
ClusterRoleのmanifestを作成します。
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: confined-role
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list"]
適応します。
# kubectl apply -f clusterRole.yaml
clusterrole.rbac.authorization.k8s.io/confined-role created
# kubectl get clusterrole
NAME AGE
admin 2d3h
cluster-admin 2d3h
confined-role 15s
edit 2d3h
<省略>
作成された事を確認できました。
ClusterRoleBinding
ClusterRoleBindingのmanifestを作成します。
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: confined-rolebinding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: confined-role
subjects:
- apiGroup: ""
kind: ServiceAccount
name: confined-sa
namespace: default
これで、下準備ができました。
Service Accountの作成
Service Accountを作成します。
# kubectl create sa confined-sa
serviceaccount/confined-sa created
# kubectl get sa
NAME SECRETS AGE
1cb2dc0b-0ae3-4d11-8be6-134366812874 1 2d3h
confined-sa 1 15s
default 1 2d3h
# kubectl get sa confined-sa -o yaml
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: "2019-11-28T06:23:37Z"
name: confined-sa
namespace: default
resourceVersion: "272115"
selfLink: /api/v1/namespaces/default/serviceaccounts/confined-sa
uid: faecd7c4-ffd9-4d8f-a080-55eff0b4dfa8
secrets:
- name: confined-sa-token-kfsn6
上の表示では secretの箇所に、confined-sa-token-kfsn6 と出てきました。
この表示されたSecretをyaml形式で取得し、Tokenを確認します。
# kubectl get secret confined-sa-token-kfsn6 -o yaml
apiVersion: v1
data:
ca.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMrekNDQWVPZ0F3SUJBZ0lVVWdkdHNzcmxuTk5PRnZUdkpiamorbEdadjh3d0RRWUpLb1pJaHZjTkFRRUwKQlFBd0RURUxNQWtHQTFVRUF4TUNZMkV3SGhjTk1Ua3hNVEkxTVRJd05qSTNXaGNOTWpNeE1USTFNVEl3TmpJMwpXakFOTVFzd0NRWURWUVFERXdKallUQ0NBU0l3RFFZSktvWklodmNOQVFFQkJRQURnZ0VQQURDQ0FRb0NnZ0VCCkFOZGhFUzlobG81R2d4YUt3dWY1cmJlSTlYRTBJaVc0cWk5MkNUS1d5RmMxSXprV3FFRm40a0JYY1h3TlFJQ28KL09TdzJ1QTVGU0JJYzZyc3hSNjNiMVhEYjlDQWVWRkFGNG9XNXRWbW5qOW53cEMvVCtSZDFiMFFmMjZ3ckI4OQpQZmdqK0pod0UvUnBMc0tEUTJrQmkrUEpzbUlCTmpHdjAwMnNOTW9rYTVuNCtzU2ZGTkhkV2ErMUJGcWxGbUhiCmcxc0c3VEI5Y28yb25jTndabGxkemJKSUhYQXVRcC9RWkQ0QW9GRUhIRFZoMjBxZ1VXUFZBNkJlcklCaVorN28Ka0Z1eTdpcHB5RFdWSkhmTFBZRlF6MFppaHpkTkpCQkhKdDcvVFNNQTlidy9TZ0ZydUsrUXIzMUhaOXJpZ0M4TgpTU3B5djVIMjNmbG5HOE9ldHlIdkw5OENBd0VBQWFOVE1GRXdIUVlEVlIwT0JCWUVGTzIxT0I1TUtOZlhMWjRXClJKQnlkZVBacWpPSk1COEdBMVVkSXdRWU1CYUFGTzIxT0I1TUtOZlhMWjRXUkpCeWRlUFpxak9KTUE4R0ExVWQKRXdFQi93UUZNQU1CQWY4d0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFIcTIrSVplOU41bzZYdWFCUUhKY29sTgpQc0RCS0lUTkxlWTJvaWpaQlBEVkhqanhnR2xHWTlKc2RWRzFITWNQc1lIVnd3bTljOTVEL1hnN1V4RWwvNVp4CkRkVDVDSnNLQWxlZGhsL3oxckFRZk9FN25HOU1FdU5oSFdKdTBTMXpQYVN0dElRVVhoU3drZ2MrcnQxMThPSFYKajdKc25lWEMrcVlTK0lEV09YWFI5S2VMRXJjc256eXBtVzE2bVRBTmtPblBlQzBTWlRzUWV0UDhORFBYRis0OAppMXlWL1A3WjZsaVl3TERPQlFJOFkwZzFJOEtCTTR2RXNQUlJOOStBbkg1OTAyNCtvNklnVnptQXhmT1RhSzVMCnN0M3cwSlJRYjVGcTIwaEYxK3NCZlNFdCttc2JnNmFCNmlaMlFCMWFSZm9LdnprSW1rOUVuZTlYZkNoVEo5dz0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
namespace: ZGVmYXVsdA==
token: ZXlKaGJHY2lPaUpTVXpJMU5pSXNJbXRwWkNJNklpSjkuZXlKcGMzTWlPaUpyZFdKbGNtNWxkR1Z6TDNObGNuWnBZMlZoWTJOdmRXNTBJaXdpYTNWaVpYSnVaWFJsY3k1cGJ5OXpaWEoyYVdObFlXTmpiM1Z1ZEM5dVlXMWxjM0JoWTJVaU9pSmtaV1poZFd4MElpd2lhM1ZpWlhKdVpYUmxjeTVwYnk5elpYSjJhV05sWVdOamIzVnVkQzl6WldOeVpYUXVibUZ0WlNJNkltTnZibVpwYm1Wa0xYTmhMWFJ2YTJWdUxXdG1jMjQySWl3aWEzVmlaWEp1WlhSbGN5NXBieTl6WlhKMmFXTmxZV05qYjNWdWRDOXpaWEoyYVdObExXRmpZMjkxYm5RdWJtRnRaU0k2SW1OdmJtWnBibVZrTFhOaElpd2lhM1ZpWlhKdVpYUmxjeTVwYnk5elpYSjJhV05sWVdOamIzVnVkQzl6WlhKMmFXTmxMV0ZqWTI5MWJuUXVkV2xrSWpvaVptRmxZMlEzWXpRdFptWmtPUzAwWkRobUxXRXdPREF0TlRWbFptWXdZalJrWm1FNElpd2ljM1ZpSWpvaWMzbHpkR1Z0T25ObGNuWnBZMlZoWTJOdmRXNTBPbVJsWm1GMWJIUTZZMjl1Wm1sdVpXUXRjMkVpZlEuRnZyV1hBUUMzVXJreG1IczM1SDlkbndUbUlJLWZoME1GTVJBbEVrZjNrdU1JVHFsbWl2VUMwLThORkdYdzMybDJrQm9TWmV0T18tNnlTbjZKSno3bk10cUZPVkZfMVpDZEtnZ2M5RE9xNkVueThSMnZYRWZPOFQ4YVhTMldfQ0Zza1lPVUttSjJFRkVTSU05RlNheXo0cHpkZU12RW5ObUw1dER3b1BXVHZGSU1TSjNtbDVNLUM0ZG9rWmtWSHB6RHQxLVRhMVR0emJlejFFRmNkb200blpyUTNLZWJ3cWx5MnhDeEg3YXdreldEbkdmSWtTVFVWRkRZWkk2SnBIMURxVVVYOXpxYzBCNW9XaVdVdzZucC1lRDFsWkMycXBUZVRTUGlyUUw0aE12dDVGUlNXdFByMlVOQXZDVENZeGNLSUl6Y2NIdXRzZklSaGJ6cVpYMzBB
kind: Secret
metadata:
annotations:
kubernetes.io/service-account.name: confined-sa
kubernetes.io/service-account.uid: faecd7c4-ffd9-4d8f-a080-55eff0b4dfa8
creationTimestamp: "2019-11-28T06:23:37Z"
name: confined-sa-token-kfsn6
namespace: default
resourceVersion: "272114"
selfLink: /api/v1/namespaces/default/secrets/confined-sa-token-kfsn6
uid: aff16ff4-986b-40df-b3d4-51d300f0bb3a
type: kubernetes.io/service-account-token
このtokenの値はBase64でエンコードされているため、デコードしてあげます。
# echo -n 'ZXlKaGJHY2lPaUpTVXpJMU5pSXNJbXRwWkNJNklpSjkuZXlKcGMzTWlPaUpyZFdKbGNtNWxkR1Z6TDNObGNuWnBZMlZoWTJOdmRXNTBJaXdpYTNWaVpYSnVaWFJsY3k1cGJ5OXpaWEoyYVdObFlXTmpiM1Z1ZEM5dVlXMWxjM0JoWTJVaU9pSmtaV1poZFd4MElpd2lhM1ZpWlhKdVpYUmxjeTVwYnk5elpYSjJhV05sWVdOamIzVnVkQzl6WldOeVpYUXVibUZ0WlNJNkltTnZibVpwYm1Wa0xYTmhMWFJ2YTJWdUxXdG1jMjQySWl3aWEzVmlaWEp1WlhSbGN5NXBieTl6WlhKMmFXTmxZV05qYjNWdWRDOXpaWEoyYVdObExXRmpZMjkxYm5RdWJtRnRaU0k2SW1OdmJtWnBibVZrTFhOaElpd2lhM1ZpWlhKdVpYUmxjeTVwYnk5elpYSjJhV05sWVdOamIzVnVkQzl6WlhKMmFXTmxMV0ZqWTI5MWJuUXVkV2xrSWpvaVptRmxZMlEzWXpRdFptWmtPUzAwWkRobUxXRXdPREF0TlRWbFptWXdZalJrWm1FNElpd2ljM1ZpSWpvaWMzbHpkR1Z0T25ObGNuWnBZMlZoWTJOdmRXNTBPbVJsWm1GMWJIUTZZMjl1Wm1sdVpXUXRjMkVpZlEuRnZyV1hBUUMzVXJreG1IczM1SDlkbndUbUlJLWZoME1GTVJBbEVrZjNrdU1JVHFsbWl2VUMwLThORkdYdzMybDJrQm9TWmV0T18tNnlTbjZKSno3bk10cUZPVkZfMVpDZEtnZ2M5RE9xNkVueThSMnZYRWZPOFQ4YVhTMldfQ0Zza1lPVUttSjJFRkVTSU05RlNheXo0cHpkZU12RW5ObUw1dER3b1BXVHZGSU1TSjNtbDVNLUM0ZG9rWmtWSHB6RHQxLVRhMVR0emJlejFFRmNkb200blpyUTNLZWJ3cWx5MnhDeEg3YXdreldEbkdmSWtTVFVWRkRZWkk2SnBIMURxVVVYOXpxYzBCNW9XaVdVdzZucC1lRDFsWkMycXBUZVRTUGlyUUw0aE12dDVGUlNXdFByMlVOQXZDVENZeGNLSUl6Y2NIdXRzZklSaGJ6cVpYMzBB' |base64 -d
eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImNvbmZpbmVkLXNhLXRva2VuLWtmc242Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImNvbmZpbmVkLXNhIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiZmFlY2Q3YzQtZmZkOS00ZDhmLWEwODAtNTVlZmYwYjRkZmE4Iiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50OmRlZmF1bHQ6Y29uZmluZWQtc2EifQ.FvrWXAQC3UrkxmHs35H9dnwTmII-fh0MFMRAlEkf3kuMITqlmivUC0-8NFGXw32l2kBoSZetO_-6ySn6JJz7nMtqFOVF_1ZCdKggc9DOq6Eny8R2vXEfO8T8aXS2W_CFskYOUKmJ2EFESIM9FSayz4pzdeMvEnNmL5tDwoPWTvFIMSJ3ml5M-C4dokZkVHpzDt1-Ta1Ttzbez1EFcdom4nZrQ3Kebwqly2xCxH7awkzWDnGfIkSTUVFDYZI6JpH1DqUUX9zqc0B5oWiWUw6np-eD1lZC2qpTeTSPirQL4hMvt5FRSWtPr2UNAvCTCYxcKIIzccHutsfIRhbzqZX30A
これを、configファイルに登録してあげます。
# kubectl config set-context confined-sa --token 'eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImNvbmZpbmVkLXNhLXRva2VuLWtmc242Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImNvbmZpbmVkLXNhIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiZmFlY2Q3YzQtZmZkOS00ZDhmLWEwODAtNTVlZmYwYjRkZmE4Iiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50OmRlZmF1bHQ6Y29uZmluZWQtc2EifQ.FvrWXAQC3UrkxmHs35H9dnwTmII-fh0MFMRAlEkf3kuMITqlmivUC0-8NFGXw32l2kBoSZetO_-6ySn6JJz7nMtqFOVF_1ZCdKggc9DOq6Eny8R2vXEfO8T8aXS2W_CFskYOUKmJ2EFESIM9FSayz4pzdeMvEnNmL5tDwoPWTvFIMSJ3ml5M-C4dokZkVHpzDt1-Ta1Ttzbez1EFcdom4nZrQ3Kebwqly2xCxH7awkzWDnGfIkSTUVFDYZI6JpH1DqUUX9zqc0B5oWiWUw6np-eD1lZC2qpTeTSPirQL4hMvt5FRSWtPr2UNAvCTCYxcKIIzccHutsfIRhbzqZX30A'
Context "confined-sa" created.
ちゃんと作成されたかを確認します。
# kubectl config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
* SampleCluster SampleCluster 1cb2dc0b-0ae3-4d11-8be6-134366812874 default
confined-sa
実際にこのcontextを使用します。
# kubectl config use-context confined-sa
Switched to context "confined-sa".
再度、get-contextを打つと*
がついて、contextが切り替わったことがわかります。
podを見れるか確認します。
# kubectl get pods
The connection to the server localhost:8080 was refused - did you specify the right host or port?
これは、正しくconfigファイルが設定されていない場合に起こります。
configファイルに変更を加えます。
# vi .kube/config
編集
- context:
cluster: SampleCluster
user: confined-sa
name: confined-sa
以下を追記
- name: confined-sa
user:
token: eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImNvbmZpbmVkLXNhLXRva2VuLWtmc242Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImNvbmZpbmVkLXNhIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiZmFlY2Q3YzQtZmZkOS00ZDhmLWEwODAtNTVlZmYwYjRkZmE4Iiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50OmRlZmF1bHQ6Y29uZmluZWQtc2EifQ.FvrWXAQC3UrkxmHs35H9dnwTmII-fh0MFMRAlEkf3kuMITqlmivUC0-8NFGXw32l2kBoSZetO_-6ySn6JJz7nMtqFOVF_1ZCdKggc9DOq6Eny8R2vXEfO8T8aXS2W_CFskYOUKmJ2EFESIM9FSayz4pzdeMvEnNmL5tDwoPWTvFIMSJ3ml5M-C4dokZkVHpzDt1-Ta1Ttzbez1EFcdom4nZrQ3Kebwqly2xCxH7awkzWDnGfIkSTUVFDYZI6JpH1DqUUX9zqc0B5oWiWUw6np-eD1lZC2qpTeTSPirQL4hMvt5FRSWtPr2UNAvCTCYxcKIIzccHutsfIRhbzqZX30A
ここでcontextsを確認します。
# kubectl config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
SampleCluster SampleCluster 1cb2dc0b-0ae3-4d11-8be6-134366812874 default
* confined-sa SampleCluster confined-sa
情報が変わりました。
ここで、再度podの情報を確認していきます。
# kubectl get pods
Error from server (Forbidden): pods is forbidden: User "system:serviceaccount:default:confined-sa" cannot list resource "pods" in API group "" in the namespace "default"
しっかりブロックされました。
では、先ほど作成したClusterRoleを反映させていきます。
一旦、権限のあるContextに戻ります。
# kubectl config use-context SampleCluster
Switched to context "SampleCluster".
それでは、先ほど作っておいたclusterRoleBindingを適用します。
# kubectl apply -f clusterRoleBinding.yaml
clusterrolebinding.rbac.authorization.k8s.io/confined-rolebinding created
それでは、また先ほどのService AccountのContextに戻ります。
# kubectl config use-context confined-sa
Switched to context "confined-sa".
それでは、podが見れるかを確認します。
# kubectl get pods -n developing
NAME READY STATUS RESTARTS AGE
deploy-automation-54b5dd5779-wxnr4 1/1 Running 0 27h
できました!
ちなみに、podを作ったりはもちろんできません。
# kubectl run nginx --image nginx
kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.
Error from server (Forbidden): deployments.apps is forbidden: User "system:serviceaccount:default:confined-sa" cannot create resource "deployments" in API group "apps" in the namespace "default"
では最後に、全権限を持つユーザを消します。
# vi .kube/config
以下の2つを消す。
- context:
cluster: SampleCluster
namespace: default
user: 1cb2dc0b-0ae3-4d11-8be6-134366812874
name: SampleCluster
- name: 1cb2dc0b-0ae3-4d11-8be6-134366812874
user:
token: eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6IjFjYjJkYzBiLTBhZTMtNGQxMS04YmU2LTEzNDM2NjgxMjg3NC10b2tlbi04ZjdzbCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiIxY2IyZGMwYi0wYWUzLTRkMTEtOGJlNi0xMzQzNjY4MTI4NzQiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiI5OTc3NTI0MC1jZTQ0LTRhMjgtODNiYi04OGM2ZTNmMGI1NmMiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6ZGVmYXVsdDoxY2IyZGMwYi0wYWUzLTRkMTEtOGJlNi0xMzQzNjY4MTI4NzQifQ.Xo5MGt4Tk246lJyzoX4ZlFGuJuY8_d0V8STtA49oaUXpghA470n3CxAOjAvH0v5YCVA7iM7U1GZsvyEGXupO46jeRE0py3X3qLqAP02J8jSP5lodRfY5VoyUOgmOqcPcqRiOgYJvJLEafyANL8iRy4fB0MdxWSoczUIJWi8wZGymNbMQ7h9vwrbCRAef9k-TAmFojAFkAyckjEJ6g5mk8Hk8Tgv-SgIfd7iK8dRY6E6flghKMhRHbaq62bC6Pr2OKmHUMdp2GJrenZ04V-BGpmkf69qCiZg-fZ8seA0jO9_ri8Z65K2NjVaTeIO2My1a-7osFxdnajr6gOaWRAw_VQ
それでは、contextもきれいにします。
# kubectl config delete-context SampleCluster
deleted context SampleCluster from /root/.kube/config
# kubectl config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
* confined-sa SampleCluster confined-sa
これで、このサーバはpodしか見れないようになりました。
終わりに
こんな感じで、これ以外にも誰かにある権限をもったServerを提供することができると思いますので、参考にしていただけたら嬉しいです。