百日半狂乱

Shut the fuck up and write some code!!

gcloud config / kubectl config 事始め。

手元のgcloudに紐付く複数のaccount/project/k8s cluster/k8s namespaceを持っている場合、とにかくどのアカウントで、何のロールで、どこのプロジェクトのどのクラスタに向かってgcloudやkubectlを叩いているのか都度確認しながら作業することになる。gcloudとkubectlはそれぞれconfigというリクエストの投げ先(context)の設定をするのに重要なサブコマンドを持っていて、これらを正しく設定しないと所望のプロジェクトなりクラスタにアクセスできない。サブコマンドがどちらもconfigという名前なので、慣れてくると覚えるキーワードが少なくて大変良いが、頭の中で二つを整理しないうちは似たようなコマンドが色々出てくるので何が何やらわからなくなってくる。

また、個々の設定方法はコマンドのhelpなりドキュメントを見ればわかるが、最初は脳内に逆引き辞書的なものが存在しないので、そもそも必要なコマンドに辿り着けない。gcloud cheat sheetとかで調べればやり方的なものは出てくるけど、結局自分で触ったものしか理解できないし何より全然覚えないので、観念して自前のチートシートを書き溜めることにした。

ここではサブコマンドconfigに関わるものを中心に、クラウド上にリソースを作り始めたりする前に確認しておきたい事柄(バージョンやパーミッションなど)を書き下す。

  • コマンドのインストール
  • account/project/region/zoneをまとめて扱うnamed configurationsの設定と切り替え
  • GKE上にk8sクラスタを作成
  • master/nodeのバージョン確認とアップグレード
  • kubectlのcontext設定とnamespaceの設定と切り替え
  • kubectlに既存のk8sクラスタを認識させる (get-credentials)
  • kubectlのcontextとnamespaceの管理に便利なプロンプトとCLIの導入
  • user/service accountのロールとパーミッション確認方法

Installations

まず必要な物を手元に揃える。

Install gcloud Command

$ /usr/local/bin/google-cloud-sdk/install.sh
$ gcloud components update

Ref. Installing Google Cloud SDK  |  Cloud SDK Documentation  |  Google Cloud

$ gcloud --version
Google Cloud SDK 193.0.0
alpha 2017.09.15
beta 2017.09.15
bq 2.0.30
container-builder-local
core 2018.03.09
gsutil 4.28
kubectl

Ref. Google Cloud SDK - Release Notes  |  Cloud SDK Documentation  |  Google Cloud

Install Other Packages

macosの場合。

brew install kubernetes-helm
brew cask install minikube
brew install stern
brew install kubectx
brew install kube-ps1

sternデバッグするのに超便利。kube-ps1はプロンプトにcontextとnamespaceを表示してくれる(kubectxと合わせて後述)。

Setup .zshrc

source /usr/local/bin/google-cloud-sdk/completion.zsh.inc
source /usr/local/bin/google-cloud-sdk/path.zsh.inc
if [ $commands[kubectl] ]; then
  source <(kubectl completion zsh)
fi

if [ $commands[helm] ]; then
    source <(helm completion zsh)
fi

Ref. Install and Set Up kubectl - Kubernetes

Install Components

kubectlその他、使っているcomponentsをインストール。メジャーっぽいcomponentも平気でbeta, alphaだったりするので、これも入れておく。

$ gcloud components update
$ gcloud components install kubectl
$ gcloud components install cloud-build-local
$ gcloud components install beta
$ gcloud components install alpha
$ gcloud components list

container-builder-localはローカルでContainer Builderと同じコンテナのビルドパイプラインを実行できる優れもの。

Ref. Taming Google Container Builder – Daisuke Maki – Medium

gcloud config

以下では、複数のconfigを作成して自由に切り替えられることを確認する。

Setup Named Configurations for Each Project

複数のaccount/project/clusterを持っている場合、named configurationsの設定を意識してしておくと良い。

topicという補足のhelpがあるのでこれでnamed configurationsの概要を掴む。書いてある通り、一つのaccount/project/clusterしか管理しないんだったらconfigurationsは忘れても良い。

$ gcloud topic configurations

このnamed configurationをproject/cluster毎に複数用意しておけば、gcloud config configurations activate [config name]でconfigを切り替えられる。

Create New Configuration

gcloud initは新しいnamed configurationsの設定や既存のnamed configurationsの再設定をインタラクティブ行う。

$ gcloud init

以下では、個別の設定を対応するサブコマンドで一つずつ設定していくが、やっていることは結果的にgcloud initと同じ。

まず、以下のコマンドで現在設定済みのnamed configurationsのリストを確認。

$ gcloud config configurations list

新しいconfigを作成。

$ gcloud config configurations create my-config
Created [my-config].
Activated [my-config].

設定ファイルの場所を確認。

$ gcloud info --format='get(config.paths.active_config_path)'
/path/to/.config/gcloud/configurations/config_my-config

作成したconfigをlistで確認。作成したmy-configが追加された。今はmy-configがactive。

$ gcloud config configurations list
NAME       IS_ACTIVE  ACCOUNT               PROJECT           DEFAULT_ZONE  DEFAULT_REGION
default    False      [another account name]  [another project]  asia-east1-a  asia-east1
my-config  True

describeで空のconfigができたことを確認。ここからaccount/project/zone/regionを設定して、後で意図したGKEクラスタにアクセスできるように準備する。

$ gcloud config configurations describe my-config
is_active: true
name: my-config
properties: {}

gcloud config list で現在active状態のconfigを確認できる。設定している最中はこっちで見た方が混乱も間違いもない。

$ gcloud config list
[core]
disable_usage_reporting = False

Your active configuration is: [my-config]

Setup auth

まずはaccountを設定する。初回ログイン時は認証のためにブラウザが起動する。

$ gcloud auth login [your account name]
WARNING: `gcloud auth login` no longer writes application default credentials.
If you need to use ADC, see:
  gcloud auth application-default --help

You are now logged in as [your account name].
Your current project is [None].  You can change this setting by running:
  $ gcloud config set project PROJECT_ID

authしたメールアドレス([your account name])がaccountに設定されていることを確認。

$ gcloud config list
[core]
account = [your account name]
disable_usage_reporting = False

Your active configuration is: [my-config]

複数のgoogleアカウントでloginすることができる。loginしたgoogleアカウントをlistで確認。ここにはauthしたservice accountも含まれる。どのアカウントを使っているかはactivateしているconfigに依存する。

$ gcloud auth list
$ gcloud auth describe [your account name]

Handle the error of google: could not find default credentials.

ずっと問題なく gcloud/kubectlコマンドを使えていたのに、ある日突然以下のエラーが出て、GKEにアクセスできなくなった。

google: could not find default credentials. See https://developers.google.com/accounts/docs/application-default-credentials for more information.

$ gcloud auth application-default login

で再認証する。

gcloud auth login, gcloud init, gcloud config set account MY_ACCOUNT等の認証とはまた別の話なので、慌てず gcloud auth application-default loginを叩く。

Ref. gcloud auth application-default login  |  Cloud SDK  |  Google Cloud

Ref. kubernetes - Could not find default credentials - Stack Overflow

Setup project

projectを設定する。authしたgoogleアカウントに紐付くprojectを確認。

$ gcloud projects list

所望のprojectを設定する。

$ gcloud config set project [your project name]
Updated property [core/project].

Setup region/zone

$ gcloud compute regions list
$ gcloud config set compute/region asia-northeast1
$ gcloud compute zones list
$ gcloud config set compute/zone asia-northeast1-a

Ref. Regions and Zones  |  Compute Engine Documentation  |  Google Cloud

これで最低限必要なconfigが揃った。

$ gcloud config list
[compute]
region = asia-northeast1
zone = asia-northeast1-a
[core]
account = [your account name]
disable_usage_reporting = False
project = [your project name]

Your active configuration is: [my-config]

他のconfigからいつでもこのconfigに戻ってこれる。

$ gcloud config configurations activate my-config
Activated [my-config].

ちなみにactive状態でない別のconfigを単発のgcloudコマンドに適用できる。

$ gcloud container clusters list --configuration=[another-config]
$ export CLOUDSDK_ACTIVE_CONFIG_NAME=[another-config]; gcloud container clusters list

Manage k8s Cluster on GKE

ここでは上記で設定したconfigを元にGKE上にk8sクラスタを新規作成、バージョンの確認、アップグレード、等を行う。

Create k8s clusters on GKE

現在のactivateになっているconfigを元にGKE上に最小のクラスタを立ち上げる。

$ gcloud config configurations list
$ gcloud config list
$ gcloud compute machine-types list
$ gcloud container clusters create hands-on --machine-type=g1-small --num-nodes=1

余談: f1-micro

インスタンスタイプf1-microをus regionで起動すれば、1インスタンスまでは無料枠が適用される。

  • 1 f1-micro instance per month (US regions only, excluding Northern Virginia)

とあるようにus-east4 (Northern Virginia)は無料にならないので注意。

ラッキー、k8s on GKEが無料!と思ってgcloud container clusters createを叩いたらf1-micro選ぶんだったらnodeは3つ起動しろと怒られた(2018/03/21時点)。残念。

ERROR: (gcloud.container.clusters.create) ResponseError: code=400, message=Clusters of f1-micro instances must contain at least 3 nodes. Please make the cluster larger or use a different machine type.

Ref. Always Free Usage Limits  |  Google Cloud Platform Free Tier  |  Google Cloud

Versioning and Upgrades

リリースノートを見るとバージョンは結構頻繁にアップグレードされるっぽい。

Ref. Release Notes  |  Kubernetes Engine  |  Google Cloud

新しいクラスタに入るk8sのバージョンはstable releaseとしてdefaultClusterVersionで指定されているバージョンで作成される。

The Kubernetes Engine team periodically performs automatic upgrades of your cluster masterto newer stable versions of Kubernetes.

とあるように、masterのアップグレードはほっといても自動で行われる(すげぇ)。

Ref. Versioning and Upgrades  |  Kubernetes Engine  |  Google Cloud

Node Auto-Upgrades

--enable-autoupgradeオプションでNode Auto-Upgradesを有効にしておけば、nodeのアップグレードも自動化できる(すげぇ)。

gcloud container clusters create --machine-type=g1-small --num-nodes=1 --enable-autoupgrade

nodeの自動アップグレード時、nodeは常にmasterのバージョンに追従する。

既存のクラスタは以下で有効化。

$ gcloud container node-pools list --cluster=hands-on # Check the target node pool name (default-pool)
$ gcloud container node-pools update default-pool --cluster hands-on --zone asia-northeast1-a --enable-autoupgrade
$ gcloud container clusters describe hands-on --format 'yaml(nodePools[].management)' # Check the updated config
nodePools:
- management:
    autoUpgrade: true

以下で無効化。

$ gcloud container node-pools update default-pool --cluster hands-on --zone asia-northeast1-a --no-enable-autoupgrade

Ref. Auto-upgrading nodes  |  Kubernetes Engine  |  Google Cloud

Node Auto-Repair

--enable-autorepairでNodeの自動修復もできるっぽい。

Ref. Auto-repairing nodes  |  Kubernetes Engine  |  Google Cloud

既存のクラスタは以下で有効化。Node Auto-Upgradesと同様に、node poolの単位で設定可能。

$ gcloud container node-pools update default-pool --cluster hands-on --zone asia-northeast1-a --enable-autorepair
$ gcloud container clusters describe hands-on --format 'yaml(nodePools[].management)' # Check the result
nodePools:
- management:
    autoRepair: true
    autoUpgrade: true

以下で無効化。

$ gcloud container node-pools update default-pool --cluster hands-on --zone asia-northeast1-a --no-enable-autorepair

修復は複数のnodeに対して同時に走る場合がある。また、一度走り出した修復は途中でNode Auto-Repairを無効化してもキャンセルされない。

Maintenance Window

自動アップグレードの時間帯を調整できる。

Ref. Maintenance Window  |  Kubernetes Engine  |  Google Cloud

既存のクラスタには以下で設定。

$ gcloud container clusters update hands-on --maintenance-window 16:00
$ gcloud container clusters describe hands-on --format 'yaml(maintenancePolicy)'
maintenancePolicy:
  window:
    dailyMaintenanceWindow:
      duration: PT4H0M0S
      startTime: '16:00'

以下で削除。

$ gcloud container clusters update hands-on --maintenance-window None

Upgrade k8s to the latest version

2018/06/30の時点では、defaultClusterVersion1.9.7-gke.3になっている。

$ gcloud container get-server-config --zone asia-northeast1-a --format 'value(defaultClusterVersion)'
Fetching server config for asia-northeast1-a
1.9.7-gke.3

作ったクラスタdefaultClusterVersionで指定されているバージョン。

$ gcloud container clusters list
NAME      LOCATION           MASTER_VERSION  MASTER_IP     MACHINE_TYPE  NODE_VERSION  NUM_NODES  STATUS
hands-on  asia-northeast1-a  1.9.7-gke.3     35.200.90.71  g1-small      1.9.7-gke.3   1          RUNNING

やっぱり最新のバージョンを使いたいので、作ったクラスタのバージョンをlatestにしてみる。

gcloud container get-server-configで指定できるバージョンの一覧を確認。

$ gcloud container get-server-config --zone asia-northeast1-a # Note that there is `defaultClusterVersion`

--cluster-version=latestで、最新版にアップグレード。

$ gcloud container clusters upgrade hands-on --master --cluster-version=latest
$ gcloud container clusters upgrade hands-on # Upgrade nodes following master's version
$ gcloud container clusters list
NAME      LOCATION           MASTER_VERSION  MASTER_IP     MACHINE_TYPE  NODE_VERSION  NUM_NODES  STATUS
hands-on  asia-northeast1-a  1.10.5-gke.0    35.200.90.71  g1-small      1.10.5-gke.0  1          RUNNING

その他、

  • nodeはmasterのバージョンを越えることができないので、masterのバージョンアップから先に行う必要がある
  • この手動アップグレードを行なった後のmasterとnodeの自動アップグレードの基準がわからない。常に最新?自動更新してくれなくなる?(TODO: 確認)
  • masterは一度バージョンを上げるとダウングレードできない。nodeはダウングレードできる。
  • バージョンアップ時にNodeが一つずつ削除→再作成されるので、hostPathemptyDirにあるデータは消える。残したいデータはpersistent diskに退避する(TODO: 後で試す)。

Ref. Upgrading a Cluster  |  Kubernetes Engine  |  Google Cloud

Ref. Versioning and Upgrades  |  Kubernetes Engine  |  Google Cloud

Get and List Operations for Google Kubernetes Engine Clusters

ここまでやってきたGKEへの操作履歴を確認できる。statusの確認やまだbetaだけどcancelもできるっぽい。

$ gcloud container operations list
$ gcloud container operations describe [OPERATION_ID]

Ref. Upgrading a Cluster  |  Kubernetes Engine  |  Google Cloud

Delete Created k8s Cluster

不要になったクラスタはさっさと削除して節約する。

$ gcloud container clusters delete hands-on
The following clusters will be deleted.
 - [hands-on] in [asia-northeast1-a]

Do you want to continue (Y/n)?

Deleting cluster hands-on...done.
Deleted [https://container.googleapis.com/v1/projects/<your project name>/zones/asia-northeast1-a/clusters/hands-on].

kubectl with GKE

ここからやっとkubectlのconfigを触る。

ちなみに、公式のチートシートがある。

Ref. kubectl Cheat Sheet - Kubernetes

How to Switch Current Context

GKE上にk8sクラスタを作った直後はcurrent-contextが作ったクラスタのcontextに切り替わっている。

$ kubectl config current-context
gke_[your project name]_asia-northeast1-a_hands-on

例えば、ローカルのdocker-for-desktopにcontextを切り替えてみる。

$ kubectl config current-context
gke_[your project name]_asia-northeast1-a_hands-on
$ kubectl config get-contexts
CURRENT   NAME                                                           CLUSTER                                                        AUTHINFO                                                       NAMESPACE
          docker-for-desktop                                             docker-for-desktop-cluster                                     docker-for-desktop                                             staging
*         gke_[your project name]_asia-northeast1-a_hands-on                 gke_[your project name]_asia-northeast1-a_hands-on                 gke_[your project name]_asia-northeast1-a_hands-on
          minikube                                                       minikube                                                       minikube
$ kubectl config use-context docker-for-desktop
Switched to context "docker-for-desktop".
$ kubectl config current-context
docker-for-desktop

How to switch namespace with kubectl

使っているcontextが複数のnamespacesを持つ場合、以下の方法でnamespaceを切り替える。覚えれば良いとは言え少し煩雑。後述のkubensの方がシンプル。

$ kubectl get namespaces
$ kubectl config set-context $(kubectl config current-context) --namespace=staging
Context "docker-for-desktop" modified.
$ kubectl config view | grep namespace:
    namespace: staging

Ref. Namespaces - Kubernetes

How to get credentials from an existing kubernetes cluster

すでに稼働しているGKE上のクラスタへの操作を始めたい場合は、まずgcloud container get-credentialsでkubectlコマンドにクラスタ認識させる必要がある。 config(account/project/region/zone)が全て正しくないとcredentialsを取ることができないので注意する。

$ gcloud auth list
$ gcloud config list
$ gcloud container clusters list
$ gcloud container clusters get-credentials [culster name]

get-credentialsを実行した時点でcontextが切り替わる。以降は、別のcontextに切り替えてもuse-contextで戻ってこれる。ちなみにuse-contextはタブ補完が効く。kubectlもgcloudもタブ補完周りは本当に気が利いていると思う。

$ kubectl config get-contexts
$ kubectl config use-context [context name]
$ kubectl cluster-info

get-credentialsで取ってきたaccess-token等の情報は~/.kube/configに格納される。

kubectlが認識済みのcontextはconfig viewで一覧できる。

$ kubectl config view

Packages for Contexts

kubectlでは今どのcontextを使っているかが重要なので、どのアカウントのどのクラスタに向かってコマンドを叩いているのかを常に把握しておきたい、なんて考えていたらtwitterのタイムラインに丁度良いツイートが流れていた。

kube-ps1

kube-ps1はプロンプトに現在のcontextとnamespaceを表示する。(zshなら)以下ですぐに試せる。

brew install kube-ps1
$ wget https://raw.githubusercontent.com/jonmosco/kube-ps1/master/kube-ps1.sh -O /usr/local/bin/kube-ps1.sh
$ source /usr/local/bin/kube-ps1.sh; export PROMPT="$(kube_ps1) $PROMPT"

自分は気に入ったので.zshrcに仕込んだ。

f:id:doi-t:20180321195140p:plain

自分の環境(oh-my-zsh)では一つ問題があって、kube<Tab>と打った時に、不必要な環境変数がたくさん出るようになった。消したい。

ちなみに、kubeon/kubeoffで表示のon/offもできる。

$ kubeon
$ kubeoff

bash用の設定方法やカスタマイズ方法はREADMEにある。

Ref. GitHub - jonmosco/kube-ps1: Kubernetes prompt info for bash and zsh

kubectx / kubens

kubectl config use-contextでcontextを切り替えたり、kubectlでnamespace切り替える代わりにkubectxkubensも使える。

brew install kubectx
$ kubectx # List up all contexts
$ kubectx docker-for-desktop
$ kubectx -
$ kubens # List up all namespaces
$ kubens staging
$ kubens -

-でどちらも一つ前のcontextやnamespaceに戻れる。

Ref. GitHub - ahmetb/kubectx: Fast way to switch between clusters and namespaces in kubectl – [✩Star] if you're using it!

How to Authenticate Service Account

Googleアカウントでauthする他に、service accountでauthすることもできる。 GoogleアカウントがAWSで言う所のIAM Userでservice accountがIAM Role?service accountは基本IAM Role的にNode(Pod)に紐づけるもの?サービス毎に権限を絞ったservice accountで安全に作業した場合はこれをローカルでも使う?等々、まだあんまり触れていないので色々疑問が残っている(要確認)。

手順に従って、鍵が入ったファイルをダウンロードしてきてからactivateする。

 $ gcloud iam service-accounts keys create \
            --iam-account my-iam-account@somedomain.com key.json
$ gcloud auth activate-service-account --key-file='./key.json'
$ gcloud auth list
$ gcloud auth describe [service account name]

Ref. Authorizing Cloud SDK tools  |  Cloud SDK Documentation  |  Google Cloud

How to Check User/Service Account Permissions

現在使っているアカウント(user or service account)にはどのようなロールが割り当てられており、ロールがどのような権限を持っているかを確認する。project単位でアカウントのロールの一覧を見ることができる(指定したuser/service accountに紐付くロールだけを一覧するやり方がわからない!!)。

$ gcloud projects get-iam-policy [your project name]
......
- members:
  - user:[your gmail address]
  role: roles/owner
  ......

そこから確かめたいuserなりservice accountに紐付くroleの権限を以下で確認する。

$ gcloud iam roles describe roles/owner

Ref. Understanding Roles  |  Cloud Identity and Access Management Documentation  |  Google Cloud

Make sure gs object's ACL

余談になるが、権限周りで、もう一つ。クラウドストレージでスタティックWebページをホスティングする場合、オブジェクトのACLの設定を適切に設定しておかないといけない。 ドキュメントにあるように、htmlファイルをアップロードした後に、aclにAllUsersの権限を追加する。

gsutil acl ch -u AllUsers:R gs://www.example.com/index.html

ここで言いたいのは、設定した権限の確認方法。gsutil ls -Lでオブジェクトに設定されているACLを確認する。gsutil cpはデフォルトだとアップロードした人にしか見えなくなるようにACLを上書きしてしまう。

$ gsutil ls -L gs://bucket/obj1

対処方法含めてACLについてはhelpとドキュメントを参照。

$ gsutil help acl

Ref. https://cloud.google.com/storage/docs/hosting-static-website:acl

etc...

その他、自分の必要に応じて随時更新。