Kubernetes Hardwayメモ

k8sクラスタはkubeadmとかrkeとかを使うと、クラスタに必要なコンポーネントを自動で作成してくれたりしてある程度楽に構築できます。しかし、あえてそれらを手作業でデプロイしていって、手動でk8sクラスタを構築したいって人はKubernetes Hardway(下記リンク)を参考にして進めるといいです。これ結構勉強になるハンズオンです。

github.com

以下ではKubernetes Hardwayでやったこととか、注意点とかをメモしていきます。ちなみにこの記事を書いた時点でのmasterへの最新コミットは4f5cecbで、これはk8s v1.9.0対応です。

事前にk8sクラスタにはどんなコンポーネントがあるかを知っておくといいです。(下記参考)

qiita.com

Prerequisites

gcloudのインストール

gcloudコマンドはGoogle Cloud SDKコンポーネントなので、Google Cloud SDKをインストールする。

Cloud SDK のインストール  |  Cloud SDK のドキュメント  |  Google Cloud

Cloud SDKのアップデート

gcloudなどのCloud SDKのバージョンが古い場合にはgcloud components updateを実行することでアップデート可能。

Install CFSSL

cfsslインストールする

Provisioning Compute Resources

ここでふと「こういうハンズオンで冗長構成を作るとき、なんでMasterの役割があるやつは2台じゃなくて3台なんだろうな〜」とか思った。ちょっとk8sの話と脱線するけど面白い記事を見つけた。

qiita.com

スプリットブレインという言葉については知ってたけどマジョリティ(多数決)で生かす方を決定するというのは知らなかった。etcdの冗長構成を作る時は奇数台にしなくちゃいけない。

Provisioning a CA and Generating TLS Certificates

  • Cloud Flareのcfsslというツールを使ってローカルにCAを作成
  • コンポーネントに必要な証明書や秘密鍵を作成していく

CA証明書、秘密鍵の作成

$ ./cfssl gencert -initca ca-csr.json | ./cfssljson -bare ca
2018/04/23 16:35:15 [INFO] generating a new CA key and certificate from CSR
2018/04/23 16:35:15 [INFO] generate received request
2018/04/23 16:35:15 [INFO] received CSR
2018/04/23 16:35:15 [INFO] generating key: rsa-2048
2018/04/23 16:35:15 [INFO] encoded CSR
2018/04/23 16:35:15 [INFO] signed certificate with serial number 476734857894076781436314039079823636939593070907

CFSSLの使い方についてはCFSSLのWikiを参考に

github.com

Generating Kubernetes Configuration Files for Authentication

Node Authorizationついて

この記事が参考になった

qiita.com

コマンドの説明

コマンド 内容
kubectl config set-cluster kubeconfigファイルにクラスタエントリを設定(クラスタの作成)
kubectl config set-credentials kubeconfigファイルにユーザーのエントリを設定(ユーザーの作成)
kubectl config set-context コンテキストを作成し、クラスタとユーザーを関係付ける。今回はdefaultという名前のコンテキストを作成した

余談だけどkubectl config set-context--namespaceオプションをつけるとデフォルトのネームスペースを変更できる

Generating the Data Encryption Config and Key

EncryptionConfigk8s v1.7から追加された機能。etcdのデータを暗号化する。対応しているのはetcd v3以降で、etcd v2では無効。

etcdはk8sの構成情報を保存するためのKVS。

Bootstrapping the etcd Cluster

各controllerノード(controller-0, controller-1, controller-2)でetcdを起動する。

INTERNAL_IPについて

この変数に代入されるのはインスタンスのインタフェース0に割り当てられたプライベートIPアドレス。GCEの全てのインスタンスメタデータサーバー(metadata.google.internal)にメタデータを格納していて、そこにクエリを飛ばすことでインスタンスのホスト名やインスタンスIDなどを入手できるそう。

インスタンス メタデータの格納と取得  |  Compute Engine ドキュメント  |  Google Cloud

クエリを飛ばす際はヘッダーにMetadata-Flavor: Googleをつける必要がある。また、インスタンスからのクエリ発行要求では追加の承認はいらないらしい(楽でいいね)

etcdを起動する際に指定する.pemファイル

k8s API Serverの秘密鍵と証明書(kubernetes-key.pem, kubernetes.pem)、CAの証明書(ca.pem)

Bootstrapping the Kubernetes Control Plane

各controllerノードでkube-apiserver、kube-scheduler、kube-controller-managerを起動する

kube-apiserverを起動する際に指定する.pemファイル

ca.pem, ca-key.pem, kubernetes-key.pem, kubernetes.pem

RBAC

ここ参考

qiita.com

kube-apiserverにアクセスする際、kubeletはkubernetesというユーザーとして認証される。

  • どのリソースにアクセスできるかを記述したもの: ClusterRole
  • ClusterRoleをUserに結びつけるもの: ClusterRoleBinding

また、kube-apiserver起動時--kubelet-client-certificateで指定したファイル(今回はkubernetes.pem)をクライアント証明書としてkubeletの認証に用いる。

インタフェースのプライベートIPについて

自動で10.240.0.10とか割り当てられてるのかと思ったら、「Provisioning Compute Resources」の章でcontrollerのインスタンス作成時に--private-network-ipで設定していた

Bootstrapping the Kubernetes Worker Nodes

各workerノード(worker-0, worker-1, worker-2)でkubelet, kube-proxy, containerd(コンテナランタイム)を起動する。

CNI

GKEではnetwork-pluginはkubenetになっているが、hardwayのハンズオンではcniというものを使用するらしい

kubeletを起動する際に指定する.pemファイル

ca.pem, worker-n.pem, worker-n-key.pem

Configuring kubectl for Remote Access

LBを通じてk8sAPIを外部から叩けるようにする。

Provisioning Pod Network Routes

現時点ではあるノードにで作成されたPodと、その他のノードで作成されたPodが通信できないようになっているので、ルーティングテーブルにルールを追加する

pod-cidr

「Provisioning Compute Resources」でインスタンスを作成する際に、メタデータとして設定している。

Deploying the DNS Cluster Add-on

kube-dnsのデプロイ。kube-dnsはPodとしてデプロイするのでどこかのworkerノードで動くことになる。

kube-dns.yaml

リソースが4つ作られる

$ kubectl create -f https://storage.googleapis.com/kubernetes-the-hard-way/kube-dns.yaml
service "kube-dns" created
serviceaccount "kube-dns" created
configmap "kube-dns" created
deployment "kube-dns" created
$ kubectl get service,sa,configmap,deployment --namespace=kube-system
NAME           TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)         AGE
svc/kube-dns   ClusterIP   10.32.0.10   <none>        53/UDP,53/TCP   23m

NAME          SECRETS   AGE
sa/default    1         5h
sa/kube-dns   1         23m

NAME                                    DATA      AGE
cm/extension-apiserver-authentication   1         6h
cm/kube-dns                             0         23m

NAME              DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
deploy/kube-dns   1         1         1            1           23m

addon-manager

kube-dns.yamladdonmanager.kubernetes.io/modeっていう設定が出てきた。以下参考

qiita.com

Smoke Test

スモークテストとは - IT用語辞典

kubectl port-forward

ローカルマシンのポート8080をnginxのPodの80番ポートに割り当てた

Cleaning Up

GCPのリソース削除