LoginSignup
27
10

More than 5 years have passed since last update.

ServiceAccount を作成して Pod から kubectl を使って Pod の情報を取得する

Posted at

作業メモ。

Kubernetes完全ガイド impress top gearシリーズを読みながら手元で確認した時のメモ。

Kubernetes の ServiceAccount を作成し、Pod から kubectl を実行した。

環境

$ kubectl version
Client Version: version.Info{Major:"1", Minor:"10", GitVersion:"v1.10.3", GitCommit:"2bba0127d85d5a46ab4b778548be28623b32d0b0", GitTreeState:"clean", BuildDate:"2018-05-28T20:03:09Z", GoVersion:"go1.9.3", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"11+", GitVersion:"v1.11.5-eks-6bad6d", GitCommit:"6bad6d9c768dc0864dab48a11653aa53b5a47043", GitTreeState:"clean", BuildDate:"2018-12-06T23:13:14Z", GoVersion:"go1.10.3", Compiler:"gc", Platform:"linux/amd64"}

ServiceAccount を作成して Pod から kubectl を使って Pod の情報を取得する

参考公式ドキュメント。

Configure Service Accounts for Pods

ServiceAccount の作成

ServiceAccount を作成する。
以下のマニュフェストを作成する。

sample-serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: sample-serviceaccount
  namespace: default
# ServiceAccount の作成
$kubectl apply -f sample-serviceaccount.yaml
serviceaccount "sample-serviceaccount" created

# 最初から存在する default 以外に作成した serviceaccount が存在する
$kubectl get serviceaccount
NAME                    SECRETS   AGE
default                 1         16d
sample-serviceaccount   1         35s

ServiceAccount を作成すると Secret も作成されている。

# マニュフェストにはない secret が追加されている
$kubectl get serviceaccount sample-serviceaccount -o yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","kind":"ServiceAccount","metadata":{"annotations":{},"name":"sample-serviceaccount","namespace":"default"}}
  creationTimestamp: 2019-01-05T21:07:40Z
  name: sample-serviceaccount
  namespace: default
  resourceVersion: "2175514"
  selfLink: /api/v1/namespaces/default/serviceaccounts/sample-serviceaccount
  uid: efcc6da1-112d-11e9-b090-0ae6cc179478
secrets:
- name: sample-serviceaccount-token-2tml5

# serviceaccount 名を使って secret が追加されている
$kubectl get secret
NAME                                TYPE                                  DATA      AGE
default-token-9shpr                 kubernetes.io/service-account-token   3         16d
sample-serviceaccount-token-2tml5   kubernetes.io/service-account-token   3         1m
test-secret                         Opaque                                2         5d

# Secret を見る
$kubectl get secret sample-serviceaccount-token-2tml5 -o yaml
apiVersion: v1
data:
  ca.crt: ・・・
  namespace: ZGVmYXVsdA==
  token: ・・・
kind: Secret
metadata:
  annotations:
    kubernetes.io/service-account.name: sample-serviceaccount
    kubernetes.io/service-account.uid: efcc6da1-112d-11e9-b090-0ae6cc179478
  creationTimestamp: 2019-01-05T21:07:40Z
  name: sample-serviceaccount-token-2tml5
  namespace: default
  resourceVersion: "2175513"
  selfLink: /api/v1/namespaces/default/secrets/sample-serviceaccount-token-2tml5
  uid: efce8bb3-112d-11e9-b090-0ae6cc179478
type: kubernetes.io/service-account-token

Secret はトークンと証明書から構成されている。
Pod から Kubernetes API へリクエストする場合、上記を利用する。

Pod を起動して Kubernetes API へリクエストする(NG)

Pod 作成時に ServiceAccount を指定する。
以下のように指定する事ができる。

sample-serviceaccount-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: sample-kubectl
spec:
  serviceAccountName: sample-serviceaccount
  containers:
    - name: kubectl-container
      image: lachlanevenson/k8s-kubectl:v1.10.4
      command: ["sleep", "86400"]

なお、ServiceAccount を明示的に指定しない場合 default という ServiceAccount が設定される。

作成した ServiceAccount を指定して起動してみる。
起動すると ServiceAccount の Secret がマウントされている。

$ kubectl apply -f sample-kubectl.yaml
pod "sample-kubectl" created

# secret がマウントされている
$kubectl get pod sample-serviceaccount-pod -o yaml |less
(一部略)

    volumeMounts:
    - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
      name: sample-serviceaccount-token-mcczl
      readOnly: true
    volumes:
  - name: sample-serviceaccount-token-mcczl
    secret:
      defaultMode: 420
      secretName: sample-serviceaccount-token-mcczl

# secret の情報が配置されている
$kubectl exec -it sample-kubectl -- ls /var/run/secrets/kubernetes.io/serviceaccount
ca.crt     namespace  token

Pod ではマウントした Secret を使って認証を行う。

この状態で kubectl get pods を実行してPod 情報を取得できるかやってみる。

$kubectl exec -it sample-kubectl -- kubectl get pods
Error from server (Forbidden): pods is forbidden: User "system:serviceaccount:default:sample-serviceaccount" cannot list pods in the namespace "default"
command terminated with exit code 1

この状態ではNG。
エラーメッセージに書いてあるように Pod 情報を取得する権限がないため。

権限を付与する

先程作成した ServiceAccount には Pod を取得する権限が無いために失敗した。

Kubernetes では RBAC(Role Based Access Control)を採用しており、どういった操作を出来るかということを記載した Role を作成し、ServiceAccount などの User に対して Role を紐付ける(RoleBinding)ことで権限管理を行っている。

Using RBAC Authorization

Role と RoleBiding には大きく分けて2種類ある。
基本的には設定範囲が違う。

  • namespace レベルの指定:Role と RoleBinding
  • cluster レベルの指定:ClusterRole と ClusterRoleBinding

違いとして例えば namspece レベルの Role を作成したとする。
この場合、別途新しい namespace が作成され、同じような権限の設定を行いたい時には新しい namespace の Role と Rolebinding が必要。
一方、CluserRole を作成指定場合、cluster ワイドなので新しい ClusterRole の作成は不要。
また、 Kuberntes システムコンポーネントでも ClusterRole を使っておりいくつかのプリセットも存在する。
その為、ざっくりした権限付与で良い場合、ClusterRole のプリセットを使う方法も有効。

確認してみる。

# clusterrole 一覧を確認.多くの情報が表示される.system と表示されているのが system で使っているもの
$kubectl get clusterrole
NAME                                                                   AGE
admin                                                                  16d
aws-node                                                               16d
cluster-admin                                                          16d
edit                                                                   16d
eks:node-bootstrapper                                                  16d
system:aggregate-to-admin                                              16d
system:aggregate-to-edit                                               16d
system:aggregate-to-view                                               16d
system:auth-delegator                                                  16d
system:aws-cloud-provider                                              16d
system:basic-user                                                      16d
system:certificates.k8s.io:certificatesigningrequests:nodeclient       16d
()

# view という clustrrole の詳細を確認。pod については get/list/watch が可能
$ kubectl describe clusterrole view

Name:         view
Labels:       kubernetes.io/bootstrapping=rbac-defaults
Annotations:  rbac.authorization.kubernetes.io/autoupdate=true
PolicyRule:
  Resources                                Non-Resource URLs  Resource Names  Verbs
  ---------                                -----------------  --------------  -----
()
  pods                                     []                 []              [get list watch]
  pods/log                                 []                 []              [get list watch]
  pods/status                              []                 []              [get list watch]
  horizontalpodautoscalers.autoscaling     []                 []              [get list watch]
  poddisruptionbudgets.policy              []                 []              [get list watch]

上記 clusterrole を 作成した serviceaccount に付与するために ClusterRoleBinding を作成する。

sample-clusterrolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: sample-clusterrolebinding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: view
subjects:
- kind: ServiceAccount
  name: sample-serviceaccount
  namespace: default
# ClusterRoleBinding を作成
$kubectl apply -f sample-clusterrolebinding.yaml
clusterrolebinding.rbac.authorization.k8s.io "sample-clusterrolebinding" created

# ServiceAccont の sample-serviceaccount と紐付いている
$kubectl describe clusterrolebinding sample-clusterrolebinding
Name:         sample-clusterrolebinding
Labels:       <none>
Annotations:  kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"rbac.authorization.k8s.io/v1","kind":"ClusterRoleBinding","metadata":{"annotations":{},"name":"sample-clusterrolebinding","namespace":""...
Role:
  Kind:  ClusterRole
  Name:  view
Subjects:
  Kind            Name                   Namespace
  ----            ----                   ---------
  ServiceAccount  sample-serviceaccount  default

Pod から Kubernetes API へリクエストする(OK)

権限を付与したので先程の Pod から kubectl get podsを実行する。

$ kubectl exec -it sample-kubectl -- kubectl get pods
NAME                                 READY     STATUS      RESTARTS   AGE
1-sample-pod                         1/1       Running     0          11d
2-sample-pod                         1/1       Running     0          11d
dapi-envars-fieldref                 1/1       Running     0          5d

Pod の再起動はしていないが成功。
トークンの認証は以前から成功しており、権限を付与したことで認可ができたので成功した状況と思われる。

27
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
27
10