GKEでAPIを利用してみる
GKEのAPIを利用してリソースの操作してみるメモ.
多分オンプレも同じですがまだ検証してないので動作確認したら追記します.
追記 2019/03/06
オンプレ環境下でも問題なく動きました
環境
環境は以下です.
1$ kubectl version
2Client Version: version.Info{Major:"1", Minor:"10", GitVersion:"v1.10.7", GitCommit:"0c38c362511b20a098d7cd855f1314dad92c2780", GitTreeState:"clean", BuildDate:"2018-08-20T10:09:03Z", GoVersion:"go1.9.3", Compiler:"gc", Platform:"linux/amd64"}
3Server Version: version.Info{Major:"1", Minor:"9+", GitVersion:"v1.9.7-gke.11", GitCommit:"dc4f6dda6a08aae2108d7a7fdc2a44fa23900f4c", GitTreeState:"clean", BuildDate:"2018-11-10T20:22:02Z", GoVersion:"go1.9.3b4", Compiler:"gc", Platform:"linux/amd64"}
APIの利用
とりあえず叩いてみる
公式ドキュメント記載の方法でひとまず叩いてみます
1$ APISERVER=$(kubectl config view | grep server | cut -f 2- -d ":" | tr -d " ")
2$ TOKEN=$(kubectl describe secret $(kubectl get secrets | grep default | cut -f1 -d ' ') | grep -E '^token' | cut -f2 -d':' | tr -d '\t')
3$ echo ${APISERVER}
4$ echo ${TOKEN}
取得できたら試しに叩いてみます.
1$ curl $APISERVER/api --header "Authorization: Bearer $TOKEN" --insecure
2{
3 "kind": "APIVersions",
4 "versions": [
5 "v1"
6 ],
7 "serverAddressByClientCIDRs": [
8 {
9 "clientCIDR": "0.0.0.0/0",
10 "serverAddress": "xxx.xxx.xxx.xxx"
11 }
12 ]
13}
ひとまず叩けました.
ちなみにAPISERVERはGKEの管理コンソールからも確認できます.
Google Cloud Console -> Kubernetes Engine -> クラスタ -> 任意のクラスタ -> クラスタのエンドポイントに記載があります.
APIの認証方式はいろいろあるようですが今回はサービスアカウントを用いた接続になっています.
具体的に追っていくと
1$ kubectl get sa
2NAME SECRETS AGE
3default 1 7d
このように各ネームスペースにはネームスペースと同名のサービスアカウントが作成されています.
サービスアカウントにはそれに付随する認証情報が自動で生成されています.
1$ kubectl get sa default -o yaml | grep token
2- name: default-token-xxxxxx
xxxxx部分はランダムに割当られます.
次にこのsecretsの中身からtokenを取り出します.
1$ kubectl get secrets default-token-xxxxxx -o yaml | grep token:
2 token: [TOKEN]
これでtokenが取り出せたのであとはサンプルのcurlのようにリクエストを送ることで利用できます.
ただ,ネームスペースにあるデフォルトの権限では実際にリソースにアクセスすることができません.
権限はkubectl auth can-iを使うことで確認できます.
例えば普段ノード管理に使っているマシンからネームスペースを取得できるか確認すると
1$ kubectl auth can-i list ns
2yes
3$ kubectl auth can-i list ns --as=system:serviceaccount:default:default
4no
のようになります.
実際にアクセスしてみると
1$ kubectl get ns --as=system:serviceaccount:default:default
2Error from server (Forbidden): namespaces is forbidden: User "system:serviceaccount:default:default" cannot list namespaces at the cluster scope
3$ kubectl get ns
4NAME STATUS AGE
5default Active 7d
6kube-public Active 7d
7kube-system Active 7d
のようにデフォルトのサービスアカウントではアクセスできないことがわかります.
今回は専用のサービスアカウントを作成しそれに権限を与えていきます.
専用のサービスアカウントを作る
というわけで操作用のサービスアカウントを作成します.
1$ kubectl create sa sample
2$ kubectl get sa
3NAME SECRETS AGE
4default 1 7d
5sample 1 20h
次にこのサービスアカウントへの権限を設定します.
権限は大きく2つに分けられます.
ネームスペース内だけで有効な「Role」とネームスペースをまたがって有効な「ClusterRole」です.
今回は,ClusterRoleを利用してみます.
以下のようにしてyamlを作成して権限を設定します.
今回は大雑把に発行しますが,細かく設定できるので適宜設定します.
1kind: ClusterRole
2apiVersion: rbac.authorization.k8s.io/v1
3metadata:
4 name: sample-cluster-role
5rules:
6 - apiGroups: ["*"]
7 resources: ["*"]
8 verbs: ["*"]
次にこのClusterRoleとサービスアカウントの紐づけを行う「ClusterRoleBinding」を設定します.
今回はClusterRoleなのでClusterRoleBindingになりますが,Roleとのヒモ付を行う場合は「RoleBinding」になります.
1kind: ClusterRoleBinding
2apiVersion: rbac.authorization.k8s.io/v1
3metadata:
4 name: sample-cluster-role-binding
5subjects:
6 # サービスアカウントとのヒモ付
7 - kind: ServiceAccount
8 name: sample
9 namespace: default
10# ClusterRoleとのヒモ付
11roleRef:
12 kind: ClusterRole
13 name: sample-cluster-role
14 apiGroup: rbac.authorization.k8s.io
それぞれのyamlファイルを用いてリソースを作成します.
1$ kubectl create -f clusterrole.yaml
2$ kubectl create -f culsterrolebinding.yaml
これで紐づけができたはずなのでパーミッションを確認してみます.
1$ kubectl auth can-i get ns --as=system:serviceaccount:default:sample
2yes
問題なく設定されていますね.
kubectlでも試してみます.
1$ kubectl get ns --as=system:serviceaccount:default:sample
2NAME SECRETS AGE
3default Active 7d
4kube-public Active 7d
5kube-system Active 7d
問題ないですね.
次に,API経由でのアクセスを試します.
適当に取得します.
1$ kubectl get sa sample -o yaml | grep token
2- name: sample-token-xxxxxx
3$ kubectl get secrets sample-token-xxxxxx -o yaml | grep token:
4 token: [TOKEN]
これをbase64デコードして利用するので,適当にカットして使います.
1$ TOKEN=$(kubectl get secrets sample-token-xxxxxx -o yaml | grep token: | cut -f4 -d " " | base64 -d)
さっきと同じようにcurlでAPIを叩いてみます.
1$ curl $APISERVER/api/v1/namespaces --header "Authorization: Bearer $TOKEN" --insecure | grep \"name\"
2 "name": "default",
3 "name": "kube-public",
4 "name": "kube-system",
取得できましたね.
defaultのTOKENに差し替えて試すと権限不足のエラーが出ます.
API Clientから利用してみる
次に公式提供のClientから利用してみます.
1import os
2
3from kubernetes import client, config
4
5configuration = client.Configuration()
6configuration.verify_ssl = False
7configuration.host = os.environ.get("APISERVER")
8configuration.api_key["authorization"] = os.environ.get("TOKEN")
9configuration.api_key_prefix["authorization"] = "Bearer"
10
11apiClient = client.ApiClient(configuration)
12v1 = client.CoreV1Api(apiClient)
13
14for ns in v1.list_namespace().items:
15 print(ns.metadata.name)
を実行すると
1default
2kube-public
3kube-system
のように取得できるはずです.
エラーとか
- Error from server (Forbidden): error when creating hoge.yaml
ClusterRoleを作ろうとしたらエラーが出た.
GKEではデフォルトで自分のアカウントに作成権限がないらしいので付与する必要があるらしい.
1$ gcloud info | grep Account
2Account: [example@example.com]
3$ kubectl create clusterrolebinding [なんか適当に名前をつける] \
4 --clusterrole=cluster-admin \
5 --user=example@example.com
のようにして自分にcluster-admin権限を付与する.
- verifyがFalseだけど良いの?
良くない.
secretsにあるcertをファイルに落としてとかしたらいけるはず(試してない1configuration.ssl_ca_cert = "/path/to/cert/file"