Kubernetes The Hard Way やってみた
Kubernetes を仕事で使っているにも関わらず、やったことがなかったためやってみた。 手順については本家のページに詳細に記載されているので、個人用メモとして残しておく。
kubernetes-the-hard-way
- 手順完了後の構成は以下。
- kubernetes 1.15.3
- containerd 1.2.9
- coredns v1.6.3
- cni v0.7.1
- etcd v3.4.0
- メモりながら、3 時間程度で k8s クラスタ構築までいけた。
- GCP の利用料は、$300 の無料枠で全然問題なかった。
GCP の利用開始
- GCP を有効化すると、
My First Project
なるものが出現する。 - 名前が気に入らないときは、任意の名前をプロジェクトを作成し直すこともできる。
- 今回は開発専用のプロジェクトを作成したかったため、別プロジェクトを作成。
- コンソールから簡単に作成できる。
gcloud projects create
でも作成できた模様。こっちでやればよかった。- gcloud projects create | Cloud SDK のドキュメント | Google Cloud
Google Cloud SDK のインストール
google-cloud-sdk のファイルを取得・インストールする。
- curl で拾ったものを直接解凍するようにした。
❯ curl -sL https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-sdk-280.0.0-darwin-x86_64.tar.gz | tar xzvf ❯ ./google-cloud-sdk/install.sh
データ収集の同意が出るので、許可しないように選択。
- プロンプトにも出ている、
gcloud config set disable_usage_reporting false
でもできる。
❯ ./google-cloud-sdk/install.sh Welcome to the Google Cloud SDK! To help improve the quality of this product, we collect anonymized usage data and anonymized stacktraces when crashes are encountered; additional information is available at <https://cloud.google.com/sdk/usage-statistics>. This data is handled in accordance with our privacy policy <https://policies.google.com/privacy>. You may choose to opt in this collection now (by choosing 'Y' at the below prompt), or at any time in the future by running the following command: gcloud config set disable_usage_reporting false Do you want to help improve the Google Cloud SDK (y/N)? N
- プロンプトにも出ている、
処理の最後に、PATH を通すように設定を促される。
.zshrc
が変更されないようにしたかったため、.zshrc.local
にファイルを設定した。- 勝手にバックアップされるのね…(
.zshrc.local.backup
は削除した。)
Modify profile to update your $PATH and enable shell command completion? Do you want to continue (Y/n)? Y The Google Cloud SDK installer will now prompt you to update an rc file to bring the Google Cloud CLIs into your environment. Enter a path to an rc file to update, or leave blank to use [/Users/m1yam0t0/.zshrc]: /Users/m1yam0t0/.zshrc.local Backing up [/Users/m1yam0t0/.zshrc.local] to [/Users/m1yam0t0/.zshrc.local.backup]. [/Users/m1yam0t0/.zshrc.local] has been updated.
バージョンが微妙に古いので、アップデートした。
❯ gcloud components update (いろいろ変更点が表示されるので、問題なければ Y と入力) Do you want to continue (Y/n)? Y
gcloud の設定の初期化
- 複数プロジェクトがある場合は、以下のように選択できるので、自分が使いたいプロジェクトを選択する。
❯ gcloud init … You are logged in as: [xxx@gmail.com]. Pick cloud project to use: [1] xxxxx (プライベートなやつなので文字は伏せた) [2] the-method-270404 [3] Create a new project Please enter numeric choice or text value (must exactly match list item): 1 Your current project has been set to: [xxxxx].
後でプロジェクトを変更したい場合は、
gcloud config set project <変更したいプロジェクト名>
で変更できる。- 自分で作成したプロジェクトに変更し直した。
❯ gcloud config set project <自分で作成したプロジェクト名> Updated property [core/project].
compute zone を確認するときは
gcloud compute zones list
で確認できる- プロジェクトを変更したときは
gcloud auth login
でしなければならないっぽい? - 以下の画面が出てきて処理がすすまなくなった
❯ gcloud compute zones list API [compute.googleapis.com] not enabled on project [xxxxxxxxxxxx]. Would you like to enable and retry (this will take a few minutes)? (y/N)? y Enabling service [compute.googleapis.com] on project [xxxxxxxxxxxx]…
gcloud auth login
しなおしたら、zone の一覧が取得できた
❯ gcloud compute zones list NAME REGION STATUS NEXT_MAINTENANCE TURNDOWN_DATE us-east1-b us-east1 UP us-east1-c us-east1 UP us-east1-d us-east1 UP
- region 一覧もとれた
❯ gcloud compute regions list NAME CPUS DISKS_GB ADDRESSES RESERVED_ADDRESSES STATUS TURNDOWN_DATE asia-east1 0/8 0/2048 0/8 0/1 UP asia-east2 0/8 0/2048 0/8 0/1 UP asia-northeast1 0/8 0/2048 0/8 0/1 UP asia-northeast2 0/8 0/2048 0/8 0/1 UP asia-northeast3 0/8 0/2048 0/8 0/1 UP asia-south1 0/8 0/2048 0/8 0/1 UP asia-southeast1 0/8 0/2048 0/8 0/1 UP australia-southeast1 0/8 0/2048 0/8 0/1 UP europe-north1 0/8 0/2048 0/8 0/1 UP europe-west1 0/8 0/2048 0/8 0/1 UP europe-west2 0/8 0/2048 0/8 0/1 UP europe-west3 0/8 0/2048 0/8 0/1 UP europe-west4 0/8 0/2048 0/8 0/1 UP europe-west6 0/8 0/2048 0/8 0/1 UP northamerica-northeast1 0/8 0/2048 0/8 0/1 UP southamerica-east1 0/8 0/2048 0/8 0/1 UP us-central1 0/8 0/2048 0/8 0/1 UP us-east1 0/8 0/2048 0/8 0/1 UP us-east4 0/8 0/2048 0/8 0/1 UP us-west1 0/8 0/2048 0/8 0/1 UP us-west2 0/8 0/2048 0/8 0/1 UP us-west3 0/8 0/2048 0/8 0/1 UP
- プロジェクトを変更したときは
東京(asia-northeast1)にしようと思ったけど、料金が高かったので断念。
- 商用じゃない限り、日本 region 使うことなさそう。
クライアントツールのインストール
とりあえず HomeBrew でインストール。
cfssl
brew install cfssl
kubectl はバイナリをダウンロードするように記載されているが、HomeBrew でインストールした。
brew install kubernetes-cli
tmux 使うといいとあるので一応インストール
brew install tmux
- Running Commands in Parallel with tmux
- CKA で使うことを想定して、簡単な操作は覚えておいたほうがいいかもしれない。
Compute リソースの作成
- kubernetes を構築するためのインスタンスを作成する。
- GCP の理解をすすめるためにもメモしておく。
やっていること
VPC 用の Network を作成
- 色々設定するっぽいので
—subnet-mode=custom
が使われている。
- 色々設定するっぽいので
k8s クラスタ用の subnet を作成
- CIDR は
10.240.0.0/24
(254 台分の IP レンジを確保)
- CIDR は
firewall の作成
—network
で指定したネットワーク内の設定ができるっぽい。—source-ranges
で IP レンジを指定- internal (controller-worker 間) - tcp,udp,icmp
- external (外部に公開されるもの) - SSH、kube-apiserver 用のポート、ICMP
external loadbalancer (kube-apiserver 用) の外部アドレスを作成
controller 用、worker 用インスタンスの作成
- インスタンス作成スピードはやい。GCP すごい。
- やっている設定内容 (controller, master 共通)
for i in 0 1 2; do # 3台作るからforループ gcloud compute instances create controller-${i} \ —async \ # 非同期で作成させる。コマンドの終了を待たない —boot-disk-size 200GB \ # ディスクのサイズ —can-ip-forward \ # インスタンスのIPフォワーディングを有効化。忘れると作り直しらしい —image-family ubuntu-1804-lts \ # imageの指定。Ubuntu 18.04 LTS なのは以外 —image-project ubuntu-os-cloud \ # imageのプロジェクトを指定 —machine-type n1-standard-1 \ # OpenStackやAWSのFlavor的なもの —private-network-ip 10.240.0.1${i} \ # IPは固定 —scopes compute-rw,storage-ro,service-management,service-control,logging-write,monitoring \ # インスタンスの権限のようなもの —subnet kubernetes \ # 作成したsubnetを設定 —tags kubernetes-the-hard-way,controller # tagを設定 done
- GCP で作成した compute インスタンスは
gcloud compute ssh
コマンドで SSH ログインできる。
CA のプロビジョニングと TLS 証明書の作成
- コンポーネント間の TLS 通信のための証明書を作成する。
やっていること
- 証明書を作成
cfssl
コマンドで作成- CA 証明書は
-initca
オプションを付けて作成。 - 他の証明書については、作成した CA 証明書の keypair を
-ca
,-ca-key
オプションで指定。
- CA 証明書は
- 作成した証明書
- CA 証明書の作成 (
ca.pem
,ca-key.pem
) - admin 用クライアント証明書を作成 (
admin.pem
,admin-key.pem
) - kubelet 用クライアント証明書の作成 (
worker-X.pem
,worker-X-key.pem
) - kube-controller-manager 用クライアント証明書の作成 (
kube-controller-manager.pem
,kube-controller-manager-key.pem
) - kube-proxy 用クライアント証明書の作成 (
kube-proxy.pem
,kube-proxy-key.pem
) - kube-scheduler 用クライアント証明書 (
kube-scheduler.pem
,kube-scheduler-key.pem
) - kube-apiserver 用クライアント証明書の作成 (
kuberentes.pem
,kubernetes-key.pem
) - ServiceAccout 用の keypair 作成 (
service-account.pem
,service-account-key.pem
)
- CA 証明書の作成 (
- 証明書をインスタンスに送信
gcloud compute scp
コマンドを使用して送信。便利- worker に転送
- CA 証明書
- kubelet 用クライアント証明書
- controller に転送
- CA 証明書
- kube-apiserver 用クライアント証明書 - ServiceAccount 用 keypair
認証のための k8s 設定ファイルの作成
各コンポーネントが kube-apiserver とのクライアント認証のための kubeconfig を作成する。
やっていること
- kube-apiserver で公開する IP アドレスを kubeconfig に設定するための
KUBERNETES_PUBLIC_ADDRESS
変数を作成 - 各コンポーネント用の kubeconfig を作成
- kubelet
- kube-proxy
- kube-controller-manager
- kube-scheduler
- admin
- kubeconfig をインスタンスに転送
- worker
- kubelet
- kube-proxy
- controller
- kube-controller-manager
- kube-scheduler - admin
- worker
k8s クラスタのデータ暗号化鍵を作成
- k8s が持つ情報を暗号化するための暗号化鍵を作成する。
- クラスタの状態 - アプリケーションの設定
- secret
やっていること
- 暗号化するためのハッシュ値を作成し、secret として登録するための manifest ファイルを作成
- 作成した manifest ファイルを controller に転送
etcd クラスタの構築
- k8s クラスタの状態を保持するための etcd を構築する。
やっていること
- 以下の手順を全ての controller で実施
etcd のバイナリをダウンロード、展開して必要なものだけ
/usr/local/bin
にmv
、実行権限を付与する。- etcd
- etcdctl
etcd 用 systemd の unit ファイル(
etcd.service
)を作成、/etc/systemd/system/
に配置。- kube-apiserver 証明書、CA 証明書を設定
- controller 間でクラスタを構築するために、member 情報を設定
etcd の service を起動する。(unit ファイルを追加したので、daemon-reload と enable を忘れずに。)
sudo systemctl daemon-reload sudo systemctl etcd enable sudo systemctl etcd start
etcd cluster が構築できているか確認
m1yam0t0@controller-0:~$ sudo ETCDCTL_API=3 etcdctl member list \
> --endpoints=https://127.0.0.1:2379 \
> --cacert=/etc/etcd/ca.pem \
> --cert=/etc/etcd/kubernetes.pem \
> --key=/etc/etcd/kubernetes-key.pem
3a57933972cb5131, started, controller-2, https://10.240.0.12:2380, https://10.240.0.12:2379, false
f98dc20bce6225a0, started, controller-0, https://10.240.0.10:2380, https://10.240.0.10:2379, false
ffed16798470cab5, started, controller-1, https://10.240.0.11:2380, https://10.240.0.11:2379, false
kubernetes の C-Plane (controller) の設定
- controller として必要な各種コンポーネントの設定を追加する。
やっていること
- 各種コンポーネントを起動するために必要なバイナリをダウンロード、配置
- 起動に必要な設定を追加
- kube-apiserver
- CA 証明書、kube-apiserver 用証明書、ServiceAccount 用証明書
- kubeconfig、データ暗号化鍵である
Secret
を設定する manifest ファイル - systemd 関連の設定
- kube-controller-manager
- kubeconfig
- systemd 関連の設定
- kube-scheduler
- kubeconfig
KubeSchedulerConfiguration
を設定する manifest ファイル- systemd 関連の設定
- kube-apiserver
- Systemd unit の起動
controller が機能しているか確認
HTTP ヘルスチェックを有効化
kubernetes.default.svc.cluster.local
で kube-apiserver の/healthz
エンドポイントにプロキシするための Nginx を起動する。- apt-get でインストール
- nginx 用の設定を作成、有効化する
kube-apiserver が 各 worker の kubelet にアクセスするための RBAC を作成する。
- ClusterRole
- ClusterRoleBinding
外部から kube-apiserver へアクセスするために、GCP の外部ロードバランサーのネットワークを設定する。
- forwarding-rule を使う。転送ルールのコンセプト | 負荷分散 | Google Cloud
- HTTP health check を設定。
- エンドポイントはさっき作成した
kubernetes.default.svc.cluster.local/healthz
- エンドポイントはさっき作成した
- health check を許可するために、firewall-rule を追加。
209.85.152.0/22,209.85.204.0/22,35.191.0.0/16
から health check が来るらしい。tcp 全開放
- target-pool (転送先のインスタンス一覧) を設定
- 作成した health check、転送先のインスタンス (controller-{0,1,2}) を設定
- forwarding-rule を設定
- 外部公開するアドレス
- ポート番号
- target-pool (と対応する region)
- 問題なく動作することを確認
❯ KUBERNETES_PUBLIC_ADDRESS=$(gcloud compute addresses describe kubernetes-the-hard-way \ --region $(gcloud config get-value compute/region) \ --format 'value(address)') ❯ curl --cacert ca.pem https://${KUBERNETES_PUBLIC_ADDRESS}:6443/version { "major": "1", "minor": "15", "gitVersion": "v1.15.3", "gitCommit": "2d3c76f9091b6bec110a5e63777c332469e0cba2", "gitTreeState": "clean", "buildDate": "2019-08-19T11:05:50Z", "goVersion": "go1.12.9", "compiler": "gc", "platform": "linux/amd64" }
worker の設定
worker として必要な各種コンポーネントの設定を追加する。
やっていること
- 依存関係となるパッケージを apt-get でインストール
- socat (
kubectl proxy
コマンドのため) - conntrack
- ipset
- socat (
- Swap の無効化
- Swap を有効化していると、デフォルトでは
kubelet
が起動しない。 - 無理やり動かすこともできるが非推奨。
- Swap を有効化していると、デフォルトでは
- 各種コンポーネントを起動するために必要なバイナリをダウンロード、配置
- worker として必要なコンポーネントを起動するための設定を追加する。
- CNI
- bridge と loopback インターフェースを作成
- containerd
- containerd の設定ファイル
- systemd 関連の設定
- kubelet
- kubelet 用証明書
- kubeconfig
KubeletConfiguration
を設定する manifest ファイル- systemd 関連の設定
- CoreDNS と
systemd-resolved
で名前解決がループしないようにホストの/etc/systemd/resolve/resolv.conf
を設定する
- CoreDNS と
- kube-proxy
- kubeconfig
KubeProxyConfiguration
を設定する manifest ファイル- systemd 関連の設定
- Systemd unit の起動
worker の動作確認
kubectl get nodes
で worker の取得できるか確認
❯ gcloud compute ssh controller-0 \
—command “kubectl get nodes --kubeconfig admin.kubeconfig"
NAME STATUS ROLES AGE VERSION
worker-0 Ready <none> 31s v1.15.3
worker-1 Ready <none> 31s v1.15.3
worker-2 Ready <none> 31s v1.15.3
リモートから kubectl でアクセスできるようにするための設定
- この時点だと、controller のインスタンス上でしか
kubectl
コマンドが利用できないため、リモートからでもアクセス可能にするための設定を追加する
やっていること
- kubeconfig の設定
- 事前に用意した admin 用 のクライアント証明書を使う
kubectl
で動作確認- 普通にできた
Pod Network の設定
- GCP の rouing 機能を使用し、Pod Network が指定されたときに、対応する Node の IP を経由するように設定する。
クラスタ内 DNS (CoreDNS) を Addon としてデプロイ
kubernetes-the-hard-way/12-dns-addon.md at master · kelseyhightower/kubernetes-the-hard-way · GitHub
- クラスタ内 DNS の動作確認方法は、業務でもたまに使うため備忘録がてら残しておく。
- Verification
- Busybox を Pod として起動
kubectl exec
でnslookup kubernetes
してクラスタ内ドメインの設定を確認
Smoke Test
- 特に問題なく動作確認完了。
確認したこと
secret が暗号化されているか
- etcd の データを参照して確認
❯ gcloud compute ssh controller-0 \ --command "sudo ETCDCTL_API=3 etcdctl get \ --endpoints=https://127.0.0.1:2379 \ --cacert=/etc/etcd/ca.pem \ --cert=/etc/etcd/kubernetes.pem \ --key=/etc/etcd/kubernetes-key.pem\ /registry/secrets/default/kubernetes-the-hard-way | hexdump -C" 00000000 2f 72 65 67 69 73 74 72 79 2f 73 65 63 72 65 74 |/registry/secret| 00000010 73 2f 64 65 66 61 75 6c 74 2f 6b 75 62 65 72 6e |s/default/kubern| 00000020 65 74 65 73 2d 74 68 65 2d 68 61 72 64 2d 77 61 |etes-the-hard-wa| 00000030 79 0a 6b 38 73 3a 65 6e 63 3a 61 65 73 63 62 63 |y.k8s:enc:aescbc| 00000040 3a 76 31 3a 6b 65 79 31 3a 00 14 8e 28 e0 5b 84 |:v1:key1:...(.[.| 00000050 53 78 b2 9c 6d 0a 4f c5 d3 37 ae 29 77 60 8a 49 |Sx..m.O..7.)w`.I| 00000060 a3 55 09 29 13 c9 0b 90 47 2d b0 b0 4a 0d be 78 |.U.)....G-..J..x| 00000070 d0 07 5c d2 73 53 92 14 bf 07 3e 6c 3c 76 e3 42 |..\.sS....>l<v.B| 00000080 4a 95 e0 2c 56 dc ab f4 b2 cb d1 5d 8f 96 58 fe |J..,V......]..X.| 00000090 98 95 7a db 2d 39 a0 1d 97 79 69 8c 93 91 46 3d |..z.-9...yi...F=| 000000a0 bd 30 ae 22 15 2c 0d 74 2d 37 1c b3 ee d3 8e 83 |.0.".,.t-7......| 000000b0 84 c3 43 69 fe 5f 6b 45 8c 69 8c 27 53 86 1d c6 |..Ci._kE.i.'S...| 000000c0 7e f6 d3 fa 87 17 90 bc fd 85 b1 5f 3c 9e 25 41 |~.........._<.%A| 000000d0 37 38 15 65 7e 81 50 48 28 68 d7 81 3c 58 05 f4 |78.e~.PH(h..<X..| 000000e0 54 1d 7e e1 30 05 df 1f d9 0a |T.~.0.....| 000000ea
NginX をデプロイして以下を確認
- Deployments リソースから、デプロイできるか
- Port Forwarding できるか
kubectl logs
でアクセスログが取れるかkubectl exec
でコマンド実行し、 NginX のバージョンが取れるかNodePort
のサービスを作成して、外部からアクセスできるか? 外部からアクセス可能にするため、GCP のfirewall-rule
を追加
さいごに
- 1 日近くかける覚悟だったが、意外とすんなり終わってしまった。
- これまでに構築したときは非常に苦戦した思い出しかないため、自分の k8s の理解度がまだまだであると認識させられた。
- GCP の無料枠全然使わなかったんだけどどうしよう…。なんか試してみたい気持ち