Edited at

Kubernetes The Hard Wayする

Kubernetesについての勉強のため、以下のとてもよくできたチュートリアルを実施したログ。

このチュートリアルではGCP上にKubernetesのクラスターをスクラッチ構築する。スクラッチインストールに関する公式ドキュメントは以下。


概要


作成するクラスターの特徴


  • 3 Master、3 Workerノード構成

  • OSはUbuntu Server 18.04

  • 各k8sコンポーネントは公式のバイナリを使用し、Systemdサービスとして稼働させる

  • API ServerはTLSで公開し、各k8sコンポーネントはそれぞれ毎にクライアント証明書を用意する


バージョン

やった時点でドキュメントに記載されていた各コンポーネントのバージョンは以下。


  • Kubernetes 1.12.0

  • containerd Container Runtime 1.2.0-rc.0

  • gVisor 50c283b9f56bb7200938d9e207355f05f79f0d17

  • CNI Container Networking 0.6.0

  • etcd v3.3.9

  • CoreDNS v1.2.2


全体の流れ

作業は14のLabに分かれており各Labではそれぞれ以下のことをする。


Prerequisites

https://github.com/kelseyhightower/kubernetes-the-hard-way/blob/master/docs/01-prerequisites.md

このLabではgcloudコマンドをセットアップする。


Google Cloud Platform

GCPのアカウントがなければサインアップする。アカウントはあったので特に何もせず。

このチュートリアルにかかるコストは0.22ドル/1時間(5.39ドル/1日)。アカウントを新規作成した場合は300ドル分のトライアルでチュートリアルを実施できるはず。


Google Cloud Platform SDK


Install the Google Cloud SDK

Google Cloud SDKを導入する

brew cask install google-cloud-sdk

.bashrcに以下を追加し、PATHを通して補完を有効にする。

source '/usr/local/Caskroom/google-cloud-sdk/latest/google-cloud-sdk/path.bash.inc'

source '/usr/local/Caskroom/google-cloud-sdk/latest/google-cloud-sdk/completion.bash.inc'

バージョンを確認する。

sotoiwa@Soto-no-MacBook-Air:~

$ gcloud version
Google Cloud SDK 221.0.0
bq 2.0.35
core 2018.10.12
gsutil 4.34
sotoiwa@Soto-no-MacBook-Air:~
$


Set a Default Compute Region and Zone

CLIを初期化し、デフォルトの地域とゾーンを設定する。

gcloud init

sotoiwa@Soto-no-MacBook-Air:~

$ gcloud config set compute/zone asia-northeast1-a
Updated property [compute/zone].
sotoiwa@Soto-no-MacBook-Air:~
$

sotoiwa@soto-no-air:~

$ gcloud config list
[compute]
region = asia-northeast1
zone = asia-northeast1-a
[core]
account = hogehoge@hogehoge.com
disable_usage_reporting = True
project = hogehoge

Your active configuration is: [default]
sotoiwa@soto-no-air:~
$


Running Commands in Parallel with tmux

tmuxを使うと同じコマンドを複数のウインドウに入力できるので便利らしい。tmuxはほとんど使ったことがないので以下のリンクを読む。

結局使わなかったが、同じコマンドを複数のペインに入力するために、最低限tmuxを使うには以下のようにする。


  • brew install tmux

  • マウススクロールができるように以下を設定する


~/.tmux.conf

set-option -g mouse on




  • tmuxでウインドウを立ち上げる


  • Ctrl+b"でペインを上下に分割する

  • もう一度Ctrl+b"でペインをさらに上下に分割する

  • マウスでペインの境界をドラッグしてペインのサイズをいい感じにする

  • 各ペインで各サーバーにログインする


  • Ctrl+b;synchronize-panesを有効化する

  • 戻すときはCtrl+b:でコマンドモードに入り、set synchronize-panes offと入力


Installing the Client Tools

https://github.com/kelseyhightower/kubernetes-the-hard-way/blob/master/docs/02-client-tools.md

このLabでは作業用のPCにkubectlcfsslをインストールする。


Install CFSSL

cfsslをインストールする。


OS X

brew install cfssl


Verification

バージョン1.2.0以上であることを確認。

sotoiwa@Soto-no-MacBook-Air:~

$ cfssl version
Version: 1.3.2
Revision: dev
Runtime: go1.10.2
sotoiwa@Soto-no-MacBook-Air:~
$


Install kubectl

kubectlをインストールする。


OS X

brewで入れたものが入ってたのでそのまま使う。


Verification

バージョン1.12.0以上であることを確認する。

sotoiwa@Soto-no-MacBook-Air:~

$ kubectl version --client
Client Version: version.Info{Major:"1", Minor:"12", GitVersion:"v1.12.2", GitCommit:"17c77c7898218073f14c8d573582e8d2313dc740", GitTreeState:"clean", BuildDate:"2018-10-30T21:39:38Z", GoVersion:"go1.11.1", Compiler:"gc", Platform:"darwin/amd64"}
sotoiwa@soto-no-air:~
$


Provisioning Compute Resources

https://github.com/kelseyhightower/kubernetes-the-hard-way/blob/master/docs/03-compute-resources.md

このLabではGCP上にネットワークとインスタンスを作成する。


Networking

最終的に以下のようなネットワークとアドレスを使用することになる。

ネットワーク/アドレス
名前
説明
設定方法

10.240.0.0/24

今回のVMインスタンスが配置されるサブネット
gcloudコマンド

10.240.0.10
controller-0
Masterノード#0のIP
gcloudコマンド

10.240.0.11
controller-1
Masterノード#1のIP
gcloudコマンド

10.240.0.12
controller-2
Masterノード#2のIP
gcloudコマンド

10.240.0.20
worker-0
Wokerノード#0のIP
gcloudコマンド

10.240.0.21
worker-1
Wokerノード#1のIP
gcloudコマンド

10.240.0.22
worker-2
Wokerノード#2のIP
gcloudコマンド

35.243.101.236

apiserverの外部公開用アドレス
gcloudコマンド

10.200.0.0/16

クラスター全体のCIDR
controller-managerの--cluster-cidrで指定

10.200.0.0/24

worker-0のPodのサブネット
CNIのブリッジネットワーク設定ファイル

10.200.1.0/24

worker-1のPodのサブネット
CNIのブリッジネットワーク設定ファイル

10.200.2.0/24

worker-2のPodのサブネット
CNIのブリッジネットワーク設定ファイル

10.32.0.0/24

Serviceで使用するアドレス範囲
apiserver(とcontroller-manager)の--service-cluster-ip-rangeで指定

10.32.0.1
kubernetes
apiserverのサービスIP
Serviceのアドレス範囲の一番目がapiserverのServiceになる

10.32.0.10
kube-dns
clusterDNSのアドレス
CoreDNSのマニフェストで指定


Virtual Private Cloud Network

VPCネットワークを作成する。


コマンド

gcloud compute networks create kubernetes-the-hard-way --subnet-mode custom



実行ログ

sotoiwa@soto-no-air:~

$ gcloud compute networks create kubernetes-the-hard-way --subnet-mode custom
Created [https://www.googleapis.com/compute/v1/projects/sotoiwa/global/networks/kubernetes-the-hard-way].
NAME SUBNET_MODE BGP_ROUTING_MODE IPV4_RANGE GATEWAY_IPV4
kubernetes-the-hard-way CUSTOM REGIONAL

Instances on this network will not be reachable until firewall rules
are created. As an example, you can allow all internal traffic between
instances as well as SSH, RDP, and ICMP by running:

$ gcloud compute firewall-rules create <FIREWALL_NAME> --network kubernetes-the-hard-way --allow tcp,udp,icmp --source-ranges <IP_RANGE>
$ gcloud compute firewall-rules create <FIREWALL_NAME> --network kubernetes-the-hard-way --allow tcp:22,tcp:3389,icmp

sotoiwa@soto-no-air:~
$


作成したVPCネットワークを確認する。

sotoiwa@soto-no-air:~

$ gcloud compute networks list
NAME SUBNET_MODE BGP_ROUTING_MODE IPV4_RANGE GATEWAY_IPV4
default AUTO REGIONAL
kubernetes-the-hard-way CUSTOM REGIONAL
sotoiwa@soto-no-air:~
$

サブネットを作成する。


コマンド

gcloud compute networks subnets create kubernetes \

--network kubernetes-the-hard-way \
--range 10.240.0.0/24


実行ログ

sotoiwa@soto-no-air:~

$ gcloud compute networks subnets create kubernetes \
> --network kubernetes-the-hard-way \
> --range 10.240.0.0/24
Created [https://www.googleapis.com/compute/v1/projects/sotoiwa/regions/asia-northeast1/subnetworks/kubernetes].
NAME REGION NETWORK RANGE
kubernetes asia-northeast1 kubernetes-the-hard-way 10.240.0.0/24
sotoiwa@soto-no-air:~
$

作成したサブネットを確認する。

sotoiwa@soto-no-air:~

$ gcloud compute networks subnets list --network kubernetes-the-hard-way
NAME REGION NETWORK RANGE
kubernetes asia-northeast1 kubernetes-the-hard-way 10.240.0.0/24
sotoiwa@soto-no-air:~
$


Firewall Rules

全てのプロトコルで内部通信を許可するルールを作成する



  • 10.240.0.0/24はVMインスタンスを配置したネットワーク


  • 10.200.0.0/16はPodが使用するアドレス範囲(クラスター全体のCIDR)


コマンド

gcloud compute firewall-rules create kubernetes-the-hard-way-allow-internal \

--allow tcp,udp,icmp \
--network kubernetes-the-hard-way \
--source-ranges 10.240.0.0/24,10.200.0.0/16


実行ログ

sotoiwa@soto-no-air:~

$ gcloud compute firewall-rules create kubernetes-the-hard-way-allow-internal \
> --allow tcp,udp,icmp \
> --network kubernetes-the-hard-way \
> --source-ranges 10.240.0.0/24,10.200.0.0/16
Creating firewall...⠏Created [https://www.googleapis.com/compute/v1/projects/sotoiwa/global/firewalls/kubernetes-the-hard-way-allow-internal].
Creating firewall...done.
NAME NETWORK DIRECTION PRIORITY ALLOW DENY DISABLED
kubernetes-the-hard-way-allow-internal kubernetes-the-hard-way INGRESS 1000 tcp,udp,icmp False
sotoiwa@soto-no-air:~
$

外部からのSSH、ICMP、HTTPSを許可する。


コマンド

gcloud compute firewall-rules create kubernetes-the-hard-way-allow-external \

--allow tcp:22,tcp:6443,icmp \
--network kubernetes-the-hard-way \
--source-ranges 0.0.0.0/0


実行ログ

sotoiwa@soto-no-air:~

$ gcloud compute firewall-rules create kubernetes-the-hard-way-allow-external \
> --allow tcp:22,tcp:6443,icmp \
> --network kubernetes-the-hard-way \
> --source-ranges 0.0.0.0/0
Creating firewall...⠏Created [https://www.googleapis.com/compute/v1/projects/sotoiwa/global/firewalls/kubernetes-the-hard-way-allow-external].
Creating firewall...done.
NAME NETWORK DIRECTION PRIORITY ALLOW DENY DISABLED
kubernetes-the-hard-way-allow-external kubernetes-the-hard-way INGRESS 1000 tcp:22,tcp:6443,icmp False
sotoiwa@soto-no-air:~
$

作成したルールを確認する。

sotoiwa@soto-no-air:~

$ gcloud compute firewall-rules list --filter="network:kubernetes-the-hard-way"
NAME NETWORK DIRECTION PRIORITY ALLOW DENY DISABLED
kubernetes-the-hard-way-allow-external kubernetes-the-hard-way INGRESS 1000 tcp:22,tcp:6443,icmp False
kubernetes-the-hard-way-allow-internal kubernetes-the-hard-way INGRESS 1000 tcp,udp,icmp False

To show all fields of the firewall, please show in JSON format: --format=json
To show all fields in table format, please see the examples in --help.

sotoiwa@soto-no-air:~
$


Kubernetes Public IP Address

API Serverの外部公開用のIPアドレスを取得する。


コマンド

gcloud compute addresses create kubernetes-the-hard-way \

--region $(gcloud config get-value compute/region)


実行ログ

sotoiwa@soto-no-air:~

$ gcloud compute addresses create kubernetes-the-hard-way \
> --region $(gcloud config get-value compute/region)
Created [https://www.googleapis.com/compute/v1/projects/sotoiwa/regions/asia-northeast1/addresses/kubernetes-the-hard-way].
sotoiwa@soto-no-air:~
$

作成されたアドレスを確認する。

sotoiwa@soto-no-air:~

$ gcloud compute addresses list --filter="name=('kubernetes-the-hard-way')"
NAME REGION ADDRESS STATUS
kubernetes-the-hard-way asia-northeast1 35.243.101.236 RESERVED
sotoiwa@soto-no-air:~
$


Compute Instances

Ubuntu Server 18.04のVMインスタンスを作成する。各インスタンスは固定のプライベートIPを持つ。


Kubernetes Controllers

Masterノード(コントロールプレーン)の3台を作成する。


コマンド

for i in 0 1 2; do

gcloud compute instances create controller-${i} \
--async \
--boot-disk-size 200GB \
--can-ip-forward \
--image-family ubuntu-1804-lts \
--image-project ubuntu-os-cloud \
--machine-type n1-standard-1 \
--private-network-ip 10.240.0.1${i} \
--scopes compute-rw,storage-ro,service-management,service-control,logging-write,monitoring \
--subnet kubernetes \
--tags kubernetes-the-hard-way,controller
done


実行ログ

sotoiwa@soto-no-air:~

$ for i in 0 1 2; do
> gcloud compute instances create controller-${i} \
> --async \
> --boot-disk-size 200GB \
> --can-ip-forward \
> --image-family ubuntu-1804-lts \
> --image-project ubuntu-os-cloud \
> --machine-type n1-standard-1 \
> --private-network-ip 10.240.0.1${i} \
> --scopes compute-rw,storage-ro,service-management,service-control,logging-write,monitoring \
> --subnet kubernetes \
> --tags kubernetes-the-hard-way,controller
> done
Instance creation in progress for [controller-0]: https://www.googleapis.com/compute/v1/projects/sotoiwa/zones/asia-northeast1-a/operations/operation-1541756265972-57a381a904121-5c3b74e7-36e449c1
Use [gcloud compute operations describe URI] command to check the status of the operation(s).
Instance creation in progress for [controller-1]: https://www.googleapis.com/compute/v1/projects/sotoiwa/zones/asia-northeast1-a/operations/operation-1541756270177-57a381ad06ae9-9ebc254c-e604d3d4
Use [gcloud compute operations describe URI] command to check the status of the operation(s).
Instance creation in progress for [controller-2]: https://www.googleapis.com/compute/v1/projects/sotoiwa/zones/asia-northeast1-a/operations/operation-1541756274215-57a381b0e085a-d986a783-47ccc0f6
Use [gcloud compute operations describe URI] command to check the status of the operation(s).
sotoiwa@soto-no-air:~
$


Kubernetes Workers

Workerノードを作成する。各ノードが使用するPodネットワークのサブネットの値(pod-cidr)をメタデータに格納しておく。クラスター全体のCIDRは後でController Managerの--cluster-cidrパラメータで指定することになり、このチュートリアルでは10.200.0.0/16を使う。各Workerノードはそのうちのぞれぞれ10.200.0.0/2410.200.1.0/2410.200.2.0/24を使う。


コマンド

for i in 0 1 2; do

gcloud compute instances create worker-${i} \
--async \
--boot-disk-size 200GB \
--can-ip-forward \
--image-family ubuntu-1804-lts \
--image-project ubuntu-os-cloud \
--machine-type n1-standard-1 \
--metadata pod-cidr=10.200.${i}.0/24 \
--private-network-ip 10.240.0.2${i} \
--scopes compute-rw,storage-ro,service-management,service-control,logging-write,monitoring \
--subnet kubernetes \
--tags kubernetes-the-hard-way,worker
done


実行ログ

sotoiwa@soto-no-air:~

$ for i in 0 1 2; do
> gcloud compute instances create worker-${i} \
> --async \
> --boot-disk-size 200GB \
> --can-ip-forward \
> --image-family ubuntu-1804-lts \
> --image-project ubuntu-os-cloud \
> --machine-type n1-standard-1 \
> --metadata pod-cidr=10.200.${i}.0/24 \
> --private-network-ip 10.240.0.2${i} \
> --scopes compute-rw,storage-ro,service-management,service-control,logging-write,monitoring \
> --subnet kubernetes \
> --tags kubernetes-the-hard-way,worker
> done
Instance creation in progress for [worker-0]: https://www.googleapis.com/compute/v1/projects/sotoiwa/zones/asia-northeast1-a/operations/operation-1541757249739-57a38553358f8-a5900c8d-449e5ada
Use [gcloud compute operations describe URI] command to check the status of the operation(s).
Instance creation in progress for [worker-1]: https://www.googleapis.com/compute/v1/projects/sotoiwa/zones/asia-northeast1-a/operations/operation-1541757252867-57a38556313ba-b4658130-00e19bc3
Use [gcloud compute operations describe URI] command to check the status of the operation(s).
Instance creation in progress for [worker-2]: https://www.googleapis.com/compute/v1/projects/sotoiwa/zones/asia-northeast1-a/operations/operation-1541757256094-57a3855945131-9896d4b4-a81fd823
Use [gcloud compute operations describe URI] command to check the status of the operation(s).
sotoiwa@soto-no-air:~
$


Verification

作成されたインスタンスを確認する。

sotoiwa@soto-no-air:~

$ gcloud compute instances list
NAME ZONE MACHINE_TYPE PREEMPTIBLE INTERNAL_IP EXTERNAL_IP STATUS
controller-0 asia-northeast1-a n1-standard-1 10.240.0.10 35.221.104.74 RUNNING
controller-1 asia-northeast1-a n1-standard-1 10.240.0.11 35.200.119.187 RUNNING
controller-2 asia-northeast1-a n1-standard-1 10.240.0.12 35.187.211.56 RUNNING
worker-0 asia-northeast1-a n1-standard-1 10.240.0.20 35.243.75.112 RUNNING
worker-1 asia-northeast1-a n1-standard-1 10.240.0.21 35.243.106.204 RUNNING
worker-2 asia-northeast1-a n1-standard-1 10.240.0.22 35.200.35.27 RUNNING
sotoiwa@soto-no-air:~
$


Configuring SSH Access

はじめてインスタンスに接続すると、SSH鍵が作成され、プロジェクトまたはインスタンスメタデータに保存される。

controller-0インスタンスへのSSHログインできることを確認する。

gcloud compute ssh controller-0


Provisioning a CA and Generating TLS Certificates

https://github.com/kelseyhightower/kubernetes-the-hard-way/blob/master/docs/04-certificate-authority.md

cfsslを使って認証局を立て、各コンポーネント用の証明書を生成する。

(参考)

https://kubernetes.io/docs/concepts/cluster-administration/certificates/


Certificate Authority

作業用PCで作業する。

ルートCAの設定ファイルのjsonを作成する。kubernetesというプロファイルを定義し、このCAが署名する証明書の有効期限と、X509v3拡張で証明書に含まれるパブリックキーの用途を指定している。後でCAから証明書を発行するときにこの設定ファイルとプロファイルを指定する。

cat > ca-config.json <<EOF

{
"signing": {
"default": {
"expiry": "8760h"
},
"profiles": {
"kubernetes": {
"usages": ["signing", "key encipherment", "server auth", "client auth"],
"expiry": "8760h"
}
}
}
}
EOF

ルートCAのCSR(証明書署名要求)を作成するためのjsonを作成する。ルートCAのCNは先頭大文字のKubernetesとしている。

cat > ca-csr.json <<EOF

{
"CN": "Kubernetes",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "US",
"L": "Portland",
"O": "Kubernetes",
"OU": "CA",
"ST": "Oregon"
}
]
}
EOF

CA秘密鍵(ca-key.pem)とCA証明書(ca.pem)を作成する。このとき証明書署名要求(ca.csr)もできる。前半のcfssl gencertコマンドが秘密鍵とCSRと証明書を作成していて、出力されたjsonをcfssljsonコマンドがファイルにしている。


コマンド

cfssl gencert -initca ca-csr.json | cfssljson -bare ca



実行ログ

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ cfssl gencert -initca ca-csr.json | cfssljson -bare ca
2018/11/11 13:17:28 [INFO] generating a new CA key and certificate from CSR
2018/11/11 13:17:28 [INFO] generate received request
2018/11/11 13:17:28 [INFO] received CSR
2018/11/11 13:17:28 [INFO] generating key: rsa-2048
2018/11/11 13:17:29 [INFO] encoded CSR
2018/11/11 13:17:29 [INFO] signed certificate with serial number 689603942501758426539296774063220033367462065061
sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way
$

鍵の内容を確認する。

openssl rsa -text -noout -in ca-key.pem

CSRの内容を確認する。

openssl req -text -noout -in ca.csr

証明書の内容を確認する。

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ openssl x509 -text -noout -in ca.pem
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
78:ca:e9:06:c9:fb:05:0c:d7:24:9e:e8:cf:9f:bd:5c:fb:ab:33:a5
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=US, ST=Oregon, L=Portland, O=Kubernetes, OU=CA, CN=Kubernetes
Validity
Not Before: Nov 11 04:12:00 2018 GMT
Not After : Nov 10 04:12:00 2023 GMT
Subject: C=US, ST=Oregon, L=Portland, O=Kubernetes, OU=CA, CN=Kubernetes
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
(省略)


Client and Server Certificates

各Kubernetesコンポーネント用のサーバー/クライアント証明書と、adminユーザー用のクライアント証明書を作成する。


The Admin Client Certificate

adminユーザーの秘密鍵と証明書を作成する。

設定ファイルを作成する。CN=adminを指定している。

cat > admin-csr.json <<EOF

{
"CN": "admin",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "US",
"L": "Portland",
"O": "system:masters",
"OU": "Kubernetes The Hard Way",
"ST": "Oregon"
}
]
}
EOF

秘密鍵と証明書を作成する。


コマンド

cfssl gencert \

-ca=ca.pem \
-ca-key=ca-key.pem \
-config=ca-config.json \
-profile=kubernetes \
admin-csr.json | cfssljson -bare admin


実行ログ

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ cfssl gencert \
> -ca=ca.pem \
> -ca-key=ca-key.pem \
> -config=ca-config.json \
> -profile=kubernetes \
> admin-csr.json | cfssljson -bare admin
2018/11/11 13:37:46 [INFO] generate received request
2018/11/11 13:37:46 [INFO] received CSR
2018/11/11 13:37:46 [INFO] generating key: rsa-2048
2018/11/11 13:37:46 [INFO] encoded CSR
2018/11/11 13:37:46 [INFO] signed certificate with serial number 194040900673817816765523470049772624081356590203
2018/11/11 13:37:46 [WARNING] This certificate lacks a "hosts" field. This makes it unsuitable for
websites. For more information see the Baseline Requirements for the Issuance and Management
of Publicly-Trusted Certificates, v.1.1.6, from the CA/Browser Forum (https://cabforum.org);
specifically, section 10.2.3 ("Information Requirements").
sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way
$

admin-key.pemadmin.csradmin.pemが作られる。

証明書を確認する。

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ openssl x509 -text -noout -in admin.pem
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
21:fd:18:4c:6d:25:82:a8:53:9c:fd:e8:4e:b0:d3:4b:21:10:0c:7b
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=US, ST=Oregon, L=Portland, O=Kubernetes, OU=CA, CN=Kubernetes
Validity
Not Before: Nov 11 04:33:00 2018 GMT
Not After : Nov 11 04:33:00 2019 GMT
Subject: C=US, ST=Oregon, L=Portland, O=system:masters, OU=Kubernetes The Hard Way, CN=admin
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
(省略)


The Kubelet Client Certificates

Kubeletのクライアント証明書を作成する。Kubeletのリクエストは特別な認可モードであるNode Authorizerで認可する(controller-managerなどはRBAC)が、そのためにはCN=system:node:<nodeName>とする必要がある。全てのWorkerノード用にKubeletのクライアント証明書を作成する。

また、KubeletはクライアントであるだけでなくKubelet APIを提供するサーバーでもあるため、生成時に-hostnameを指定している。これによって作成する証明書にはSubject Alternative Nameが含まれる。


コマンド

for instance in worker-0 worker-1 worker-2; do

cat > ${instance}-csr.json <<EOF
{
"CN": "system:node:${instance}",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "US",
"L": "Portland",
"O": "system:nodes",
"OU": "Kubernetes The Hard Way",
"ST": "Oregon"
}
]
}
EOF

EXTERNAL_IP=$(gcloud compute instances describe ${instance} \
--format 'value(networkInterfaces[0].accessConfigs[0].natIP)')

INTERNAL_IP=$(gcloud compute instances describe ${instance} \
--format 'value(networkInterfaces[0].networkIP)')

cfssl gencert \
-ca=ca.pem \
-ca-key=ca-key.pem \
-config=ca-config.json \
-hostname=${instance},${EXTERNAL_IP},${INTERNAL_IP} \
-profile=kubernetes \
${instance}-csr.json | cfssljson -bare ${instance}
done



実行ログ

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ for instance in worker-0 worker-1 worker-2; do
> cat > ${instance}-csr.json <<EOF
> {
> "CN": "system:node:${instance}",
> "key": {
> "algo": "rsa",
> "size": 2048
> },
> "names": [
> {
> "C": "US",
> "L": "Portland",
> "O": "system:nodes",
> "OU": "Kubernetes The Hard Way",
> "ST": "Oregon"
> }
> ]
> }
> EOF
>
> EXTERNAL_IP=$(gcloud compute instances describe ${instance} \
> --format 'value(networkInterfaces[0].accessConfigs[0].natIP)')
>
> INTERNAL_IP=$(gcloud compute instances describe ${instance} \
> --format 'value(networkInterfaces[0].networkIP)')
>
> cfssl gencert \
> -ca=ca.pem \
> -ca-key=ca-key.pem \
> -config=ca-config.json \
> -hostname=${instance},${EXTERNAL_IP},${INTERNAL_IP} \
> -profile=kubernetes \
> ${instance}-csr.json | cfssljson -bare ${instance}
> done
2018/11/11 13:54:09 [INFO] generate received request
2018/11/11 13:54:09 [INFO] received CSR
2018/11/11 13:54:09 [INFO] generating key: rsa-2048
2018/11/11 13:54:09 [INFO] encoded CSR
2018/11/11 13:54:09 [INFO] signed certificate with serial number 607068271717182629182608002048778592028239367009
2018/11/11 13:54:12 [INFO] generate received request
2018/11/11 13:54:12 [INFO] received CSR
2018/11/11 13:54:12 [INFO] generating key: rsa-2048
2018/11/11 13:54:12 [INFO] encoded CSR
2018/11/11 13:54:13 [INFO] signed certificate with serial number 265349660986184529136660474458334524391738562848
2018/11/11 13:54:15 [INFO] generate received request
2018/11/11 13:54:15 [INFO] received CSR
2018/11/11 13:54:15 [INFO] generating key: rsa-2048
2018/11/11 13:54:15 [INFO] encoded CSR
2018/11/11 13:54:15 [INFO] signed certificate with serial number 441273454681782563464999456585802366467077262409
sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way
$

作成されたファイルを確認する。

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ ls -l worker*
-rw-r--r-- 1 sotoiwa staff 244 11 11 13:54 worker-0-csr.json
-rw------- 1 sotoiwa staff 1679 11 11 13:54 worker-0-key.pem
-rw-r--r-- 1 sotoiwa staff 1119 11 11 13:54 worker-0.csr
-rw-r--r-- 1 sotoiwa staff 1493 11 11 13:54 worker-0.pem
-rw-r--r-- 1 sotoiwa staff 244 11 11 13:54 worker-1-csr.json
-rw------- 1 sotoiwa staff 1679 11 11 13:54 worker-1-key.pem
-rw-r--r-- 1 sotoiwa staff 1119 11 11 13:54 worker-1.csr
-rw-r--r-- 1 sotoiwa staff 1493 11 11 13:54 worker-1.pem
-rw-r--r-- 1 sotoiwa staff 244 11 11 13:54 worker-2-csr.json
-rw------- 1 sotoiwa staff 1679 11 11 13:54 worker-2-key.pem
-rw-r--r-- 1 sotoiwa staff 1119 11 11 13:54 worker-2.csr
-rw-r--r-- 1 sotoiwa staff 1493 11 11 13:54 worker-2.pem
sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way
$

worker-0の証明書を確認する。SANが含まれる。

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ openssl x509 -text -noout -in worker-0.pem
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
6a:55:e1:fd:ea:e0:e4:7a:5c:d4:cf:90:44:b5:e5:34:c4:28:8b:61
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=US, ST=Oregon, L=Portland, O=Kubernetes, OU=CA, CN=Kubernetes
Validity
Not Before: Nov 11 04:49:00 2018 GMT
Not After : Nov 11 04:49:00 2019 GMT
Subject: C=US, ST=Oregon, L=Portland, O=system:nodes, OU=Kubernetes The Hard Way, CN=system:node:worker-0
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
(省略)
X509v3 Subject Alternative Name:
DNS:worker-0, IP Address:35.243.75.112, IP Address:10.240.0.20
(省略)


The Controller Manager Client Certificate

Controller Managerの証明書はCN=system:kube-controller-managerとする。


コマンド

{

cat > kube-controller-manager-csr.json <<EOF
{
"CN": "system:kube-controller-manager",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "US",
"L": "Portland",
"O": "system:kube-controller-manager",
"OU": "Kubernetes The Hard Way",
"ST": "Oregon"
}
]
}
EOF

cfssl gencert \
-ca=ca.pem \
-ca-key=ca-key.pem \
-config=ca-config.json \
-profile=kubernetes \
kube-controller-manager-csr.json | cfssljson -bare kube-controller-manager

}



実行ログ

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ {
>
> cat > kube-controller-manager-csr.json <<EOF
> {
> "CN": "system:kube-controller-manager",
> "key": {
> "algo": "rsa",
> "size": 2048
> },
> "names": [
> {
> "C": "US",
> "L": "Portland",
> "O": "system:kube-controller-manager",
> "OU": "Kubernetes The Hard Way",
> "ST": "Oregon"
> }
> ]
> }
> EOF
>
> cfssl gencert \
> -ca=ca.pem \
> -ca-key=ca-key.pem \
> -config=ca-config.json \
> -profile=kubernetes \
> kube-controller-manager-csr.json | cfssljson -bare kube-controller-manager
>
> }
2018/11/11 14:05:17 [INFO] generate received request
2018/11/11 14:05:17 [INFO] received CSR
2018/11/11 14:05:17 [INFO] generating key: rsa-2048
2018/11/11 14:05:18 [INFO] encoded CSR
2018/11/11 14:05:18 [INFO] signed certificate with serial number 663059462179332133204598729540750202823868590760
2018/11/11 14:05:18 [WARNING] This certificate lacks a "hosts" field. This makes it unsuitable for
websites. For more information see the Baseline Requirements for the Issuance and Management
of Publicly-Trusted Certificates, v.1.1.6, from the CA/Browser Forum (https://cabforum.org);
specifically, section 10.2.3 ("Information Requirements").
sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way
$

確認する。

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ openssl x509 -text -noout -in kube-controller-manager.pem
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
74:24:9d:56:20:af:2a:3b:a1:90:4c:2a:21:1b:4b:64:9c:be:aa:a8
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=US, ST=Oregon, L=Portland, O=Kubernetes, OU=CA, CN=Kubernetes
Validity
Not Before: Nov 11 05:00:00 2018 GMT
Not After : Nov 11 05:00:00 2019 GMT
Subject: C=US, ST=Oregon, L=Portland, O=system:kube-controller-manager, OU=Kubernetes The Hard Way, CN=system:kube-controller-manager
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
(省略)


The Kube Proxy Client Certificate

Kube Proxyの証明書はCN=system:kube-proxyとする。


コマンド

{

cat > kube-proxy-csr.json <<EOF
{
"CN": "system:kube-proxy",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "US",
"L": "Portland",
"O": "system:node-proxier",
"OU": "Kubernetes The Hard Way",
"ST": "Oregon"
}
]
}
EOF

cfssl gencert \
-ca=ca.pem \
-ca-key=ca-key.pem \
-config=ca-config.json \
-profile=kubernetes \
kube-proxy-csr.json | cfssljson -bare kube-proxy

}



実行ログ

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ {
>
> cat > kube-proxy-csr.json <<EOF
> {
> "CN": "system:kube-proxy",
> "key": {
> "algo": "rsa",
> "size": 2048
> },
> "names": [
> {
> "C": "US",
> "L": "Portland",
> "O": "system:node-proxier",
> "OU": "Kubernetes The Hard Way",
> "ST": "Oregon"
> }
> ]
> }
> EOF
>
> cfssl gencert \
> -ca=ca.pem \
> -ca-key=ca-key.pem \
> -config=ca-config.json \
> -profile=kubernetes \
> kube-proxy-csr.json | cfssljson -bare kube-proxy
>
> }
2018/11/11 14:13:28 [INFO] generate received request
2018/11/11 14:13:28 [INFO] received CSR
2018/11/11 14:13:28 [INFO] generating key: rsa-2048
2018/11/11 14:13:29 [INFO] encoded CSR
2018/11/11 14:13:29 [INFO] signed certificate with serial number 419734016720855630130671555622742251431767916802
2018/11/11 14:13:29 [WARNING] This certificate lacks a "hosts" field. This makes it unsuitable for
websites. For more information see the Baseline Requirements for the Issuance and Management
of Publicly-Trusted Certificates, v.1.1.6, from the CA/Browser Forum (https://cabforum.org);
specifically, section 10.2.3 ("Information Requirements").
sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way
$

確認する。

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ openssl x509 -text -noout -in kube-proxy.pem
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
49:85:86:35:c2:1e:dc:59:66:12:4d:e6:9a:65:d1:df:45:65:41:02
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=US, ST=Oregon, L=Portland, O=Kubernetes, OU=CA, CN=Kubernetes
Validity
Not Before: Nov 11 05:08:00 2018 GMT
Not After : Nov 11 05:08:00 2019 GMT
Subject: C=US, ST=Oregon, L=Portland, O=system:node-proxier, OU=Kubernetes The Hard Way, CN=system:kube-proxy
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
(省略)


The Scheduler Client Certificate

Schedulerの証明書はCN=system:kube-schedulerとする。


コマンド

{

cat > kube-scheduler-csr.json <<EOF
{
"CN": "system:kube-scheduler",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "US",
"L": "Portland",
"O": "system:kube-scheduler",
"OU": "Kubernetes The Hard Way",
"ST": "Oregon"
}
]
}
EOF

cfssl gencert \
-ca=ca.pem \
-ca-key=ca-key.pem \
-config=ca-config.json \
-profile=kubernetes \
kube-scheduler-csr.json | cfssljson -bare kube-scheduler

}



実行ログ

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ {
>
> cat > kube-scheduler-csr.json <<EOF
> {
> "CN": "system:kube-scheduler",
> "key": {
> "algo": "rsa",
> "size": 2048
> },
> "names": [
> {
> "C": "US",
> "L": "Portland",
> "O": "system:kube-scheduler",
> "OU": "Kubernetes The Hard Way",
> "ST": "Oregon"
> }
> ]
> }
> EOF
>
> cfssl gencert \
> -ca=ca.pem \
> -ca-key=ca-key.pem \
> -config=ca-config.json \
> -profile=kubernetes \
> kube-scheduler-csr.json | cfssljson -bare kube-scheduler
>
> }
2018/11/11 14:17:29 [INFO] generate received request
2018/11/11 14:17:29 [INFO] received CSR
2018/11/11 14:17:29 [INFO] generating key: rsa-2048
2018/11/11 14:17:30 [INFO] encoded CSR
2018/11/11 14:17:30 [INFO] signed certificate with serial number 291023982831656432886923858896283759904092510905
2018/11/11 14:17:30 [WARNING] This certificate lacks a "hosts" field. This makes it unsuitable for
websites. For more information see the Baseline Requirements for the Issuance and Management
of Publicly-Trusted Certificates, v.1.1.6, from the CA/Browser Forum (https://cabforum.org);
specifically, section 10.2.3 ("Information Requirements").
sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way
$

確認する。

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ openssl x509 -text -noout -in kube-scheduler.pem
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
32:f9:f7:7b:6e:58:65:42:8f:4e:52:c2:e1:85:f0:81:8a:2e:da:b9
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=US, ST=Oregon, L=Portland, O=Kubernetes, OU=CA, CN=Kubernetes
Validity
Not Before: Nov 11 05:13:00 2018 GMT
Not After : Nov 11 05:13:00 2019 GMT
Subject: C=US, ST=Oregon, L=Portland, O=system:kube-scheduler, OU=Kubernetes The Hard Way, CN=system:kube-scheduler
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
(省略)


The Kubernetes API Server Certificate

API Serverはクラスター内部からはkubernetesというServiceとしてアクセスされるのでCN=kubernetesとする。kube-apiserverではない。また、外部からもアクセスできるようにするため、-hostnameオプションでSANに以下を指定する。

アドレス/ホスト名
説明

10.32.0.1
apiserverのServiceのIP(Serviceが使用するアドレス範囲はあとで指定するが、その1番目のアドレスになる)

10.240.0.10,10.240.0.11,10.240.0.12
各Masterノードのプライベートアドレス

${KUBERNETES_PUBLIC_ADDRESS}
外部公開用のIPアドレス

127.0.0.1
ループバックアドレス

kubernetes.default
apiserverのServiceのホスト名

(疑問)

kuberneteskubernetes.default.svckubernetes.default.svc.clusterkubernetes.default.svc.cluster.localもSANに含めた方がよいのでは?


コマンド

{

KUBERNETES_PUBLIC_ADDRESS=$(gcloud compute addresses describe kubernetes-the-hard-way \
--region $(gcloud config get-value compute/region) \
--format 'value(address)')

cat > kubernetes-csr.json <<EOF
{
"CN": "kubernetes",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "US",
"L": "Portland",
"O": "Kubernetes",
"OU": "Kubernetes The Hard Way",
"ST": "Oregon"
}
]
}
EOF

cfssl gencert \
-ca=ca.pem \
-ca-key=ca-key.pem \
-config=ca-config.json \
-hostname=10.32.0.1,10.240.0.10,10.240.0.11,10.240.0.12,${KUBERNETES_PUBLIC_ADDRESS},127.0.0.1,kubernetes.default \
-profile=kubernetes \
kubernetes-csr.json | cfssljson -bare kubernetes

}



実行ログ

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ {
>
> KUBERNETES_PUBLIC_ADDRESS=$(gcloud compute addresses describe kubernetes-the-hard-way \
> --region $(gcloud config get-value compute/region) \
> --format 'value(address)')
>
> cat > kubernetes-csr.json <<EOF
> {
> "CN": "kubernetes",
> "key": {
> "algo": "rsa",
> "size": 2048
> },
> "names": [
> {
> "C": "US",
> "L": "Portland",
> "O": "Kubernetes",
> "OU": "Kubernetes The Hard Way",
> "ST": "Oregon"
> }
> ]
> }
> EOF
>
> cfssl gencert \
> -ca=ca.pem \
> -ca-key=ca-key.pem \
> -config=ca-config.json \
> -hostname=10.32.0.1,10.240.0.10,10.240.0.11,10.240.0.12,${KUBERNETES_PUBLIC_ADDRESS},127.0.0.1,kubernetes.default \
> -profile=kubernetes \
> kubernetes-csr.json | cfssljson -bare kubernetes
>
> }
2018/11/11 14:37:02 [INFO] generate received request
2018/11/11 14:37:02 [INFO] received CSR
2018/11/11 14:37:02 [INFO] generating key: rsa-2048
2018/11/11 14:37:03 [INFO] encoded CSR
2018/11/11 14:37:03 [INFO] signed certificate with serial number 265279844700410116849351878684631182647597918003
sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way
$

確認する。

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ openssl x509 -text -noout -in kubernetes.pem
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
2e:77:8f:45:14:b3:8a:c1:0c:5a:98:57:6a:b7:a7:a1:09:66:e7:33
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=US, ST=Oregon, L=Portland, O=Kubernetes, OU=CA, CN=Kubernetes
Validity
Not Before: Nov 11 05:32:00 2018 GMT
Not After : Nov 11 05:32:00 2019 GMT
Subject: C=US, ST=Oregon, L=Portland, O=Kubernetes, OU=Kubernetes The Hard Way, CN=kubernetes
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
(省略)
X509v3 Subject Alternative Name:
DNS:kubernetes.default, IP Address:10.32.0.1, IP Address:10.240.0.10, IP Address:10.240.0.11, IP Address:10.240.0.12, IP Address:35.243.101.236, IP Address:127.0.0.1
(省略)


The Service Account Key Pair

Controller Managerで稼働するToken ControllerがService Account Tokenを生成するための秘密鍵を作成する。CN=service-accountsの証明書と秘密鍵を作成する。

(参考)

Managing Service Accounts


コマンド

{

cat > service-account-csr.json <<EOF
{
"CN": "service-accounts",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "US",
"L": "Portland",
"O": "Kubernetes",
"OU": "Kubernetes The Hard Way",
"ST": "Oregon"
}
]
}
EOF

cfssl gencert \
-ca=ca.pem \
-ca-key=ca-key.pem \
-config=ca-config.json \
-profile=kubernetes \
service-account-csr.json | cfssljson -bare service-account

}



実行ログ

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ {
>
> cat > service-account-csr.json <<EOF
> {
> "CN": "service-accounts",
> "key": {
> "algo": "rsa",
> "size": 2048
> },
> "names": [
> {
> "C": "US",
> "L": "Portland",
> "O": "Kubernetes",
> "OU": "Kubernetes The Hard Way",
> "ST": "Oregon"
> }
> ]
> }
> EOF
>
> cfssl gencert \
> -ca=ca.pem \
> -ca-key=ca-key.pem \
> -config=ca-config.json \
> -profile=kubernetes \
> service-account-csr.json | cfssljson -bare service-account
>
> }
2018/11/11 14:51:48 [INFO] generate received request
2018/11/11 14:51:48 [INFO] received CSR
2018/11/11 14:51:48 [INFO] generating key: rsa-2048
2018/11/11 14:51:48 [INFO] encoded CSR
2018/11/11 14:51:48 [INFO] signed certificate with serial number 35293248960946258940722654882849406852741852896
2018/11/11 14:51:48 [WARNING] This certificate lacks a "hosts" field. This makes it unsuitable for
websites. For more information see the Baseline Requirements for the Issuance and Management
of Publicly-Trusted Certificates, v.1.1.6, from the CA/Browser Forum (https://cabforum.org);
specifically, section 10.2.3 ("Information Requirements").
sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way
$

確認する。

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ openssl x509 -text -noout -in service-account.pem
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
06:2e:9a:a0:f0:7c:02:82:7f:2b:4e:c7:14:46:3c:5a:24:bd:ee:e0
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=US, ST=Oregon, L=Portland, O=Kubernetes, OU=CA, CN=Kubernetes
Validity
Not Before: Nov 11 05:47:00 2018 GMT
Not After : Nov 11 05:47:00 2019 GMT
Subject: C=US, ST=Oregon, L=Portland, O=Kubernetes, OU=Kubernetes The Hard Way, CN=service-accounts
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
(省略)


Distribute the Client and Server Certificates

ここまでに作成した秘密鍵・証明書は以下。

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ ls -l *.pem
-rw------- 1 sotoiwa staff 1679 11 11 13:37 admin-key.pem
-rw-r--r-- 1 sotoiwa staff 1428 11 11 13:37 admin.pem
-rw------- 1 sotoiwa staff 1675 11 11 13:17 ca-key.pem
-rw-r--r-- 1 sotoiwa staff 1318 11 11 13:17 ca.pem
-rw------- 1 sotoiwa staff 1679 11 11 14:05 kube-controller-manager-key.pem
-rw-r--r-- 1 sotoiwa staff 1484 11 11 14:05 kube-controller-manager.pem
-rw------- 1 sotoiwa staff 1679 11 11 14:13 kube-proxy-key.pem
-rw-r--r-- 1 sotoiwa staff 1452 11 11 14:13 kube-proxy.pem
-rw------- 1 sotoiwa staff 1679 11 11 14:17 kube-scheduler-key.pem
-rw-r--r-- 1 sotoiwa staff 1460 11 11 14:17 kube-scheduler.pem
-rw------- 1 sotoiwa staff 1679 11 11 14:37 kubernetes-key.pem
-rw-r--r-- 1 sotoiwa staff 1521 11 11 14:37 kubernetes.pem
-rw------- 1 sotoiwa staff 1679 11 11 14:51 service-account-key.pem
-rw-r--r-- 1 sotoiwa staff 1440 11 11 14:51 service-account.pem
-rw------- 1 sotoiwa staff 1679 11 11 13:54 worker-0-key.pem
-rw-r--r-- 1 sotoiwa staff 1493 11 11 13:54 worker-0.pem
-rw------- 1 sotoiwa staff 1679 11 11 13:54 worker-1-key.pem
-rw-r--r-- 1 sotoiwa staff 1493 11 11 13:54 worker-1.pem
-rw------- 1 sotoiwa staff 1679 11 11 13:54 worker-2-key.pem
-rw-r--r-- 1 sotoiwa staff 1493 11 11 13:54 worker-2.pem
sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way
$

それぞれの秘密鍵と証明書の最終的な行き先は次の通り。PEMファイルのまま、あるいはkubeconfigの中のBase64エンコードされたデータとして配布される。


  • admin-key.pem


    • 作業用PC:admin.kubeconfig



  • admin.pem


    • 作業用PC:admin.kubeconfig



  • ca-key.pem


    • controller-${i}:/var/lib/kubernetes/ca-key.pem



  • ca.pem


    • controller-${i}:/etc/etcd/ca.pem

    • controller-${i}:/var/lib/kubernetes/ca.pem

    • worker-${i}:/var/lib/kubernetes/ca.pem

    • worker-${i}:/var/lib/kubelet/kubeconfig

    • worker-${i}:/var/lib/kube-proxy/kubeconfig

    • controller-${i}:/var/lib/kubernetes/kube-controller-manager.kubeconfig

    • controller-${i}:/var/lib/kubernetes/kube-scheduler.kubeconfig

    • 作業用PC:admin.kubeconfig



  • kube-controller-manager-key.pem


    • controller-${i}:/var/lib/kubernetes/kube-controller-manager.kubeconfig



  • kube-controller-manager.pem


    • controller-${i}:/var/lib/kubernetes/kube-controller-manager.kubeconfig



  • kube-proxy-key.pem


    • worker-${i}:/var/lib/kube-proxy/kubeconfig



  • kube-proxy.pem


    • worker-${i}:/var/lib/kube-proxy/kubeconfig



  • kube-scheduler-key.pem


    • controller-${i}:/var/lib/kubernetes/kube-scheduler.kubeconfig



  • kube-scheduler.pem


    • controller-${i}:/var/lib/kubernetes/kube-scheduler.kubeconfig



  • kubernetes-key.pem


    • controller-${i}:/etc/etcd/kubernetes-key.pem

    • controller-${i}:/var/lib/kubernetes/kubernetes-key.pem



  • kubernetes.pem


    • controller-${i}:/etc/etcd/kubernetes.pem

    • controller-${i}:/var/lib/kubernetes/kubernetes.pem



  • service-account-key.pem


    • controller-${i}:/var/lib/kubernetes/service-account-key.pem



  • service-account.pem


    • controller-${i}:/var/lib/kubernetes/service-account.pem



  • worker-0-key.pem


    • worker-0:/var/lib/kubelet/worker-0-key.pem

    • worker-0:/var/lib/kubelet/kubeconfig



  • worker-0.pem


    • worker-0:/var/lib/kubelet/worker-0.pem

    • worker-0:/var/lib/kubelet/kubeconfig



  • worker-1-key.pem


    • worker-1:/var/lib/kubelet/worker-1-key.pem

    • worker-1:/var/lib/kubelet/kubeconfig



  • worker-1.pem


    • worker-1:/var/lib/kubelet/worker-1.pem

    • worker-1:/var/lib/kubelet/kubeconfig



  • worker-2-key.pem


    • worker-2:/var/lib/kubelet/worker-2-key.pem

    • worker-2:/var/lib/kubelet/kubeconfig



  • worker-2.pem


    • worker-2:/var/lib/kubelet/worker-2.pem

    • worker-2:/var/lib/kubelet/kubeconfig



WorkerノードにCAの証明書と各ノード(Kubelet)秘密鍵と証明書を転送する。

for instance in worker-0 worker-1 worker-2; do

gcloud compute scp ca.pem ${instance}-key.pem ${instance}.pem ${instance}:~/
done

MasterノードにCAの秘密鍵と証明書、API Serverの秘密鍵と証明書、Service Account作成用の秘密鍵と証明書をコピーする。

for instance in controller-0 controller-1 controller-2; do

gcloud compute scp ca.pem ca-key.pem kubernetes-key.pem kubernetes.pem \
service-account-key.pem service-account.pem ${instance}:~/
done

以下のコンポーネントの証明書は次のLabでkubeconfigを作成するのに使用する。


  • kube-proxy

  • kube-controller-manager

  • kube-scheduler

  • kubelet


Generating Kubernetes Configuration Files for Authentication

https://github.com/kelseyhightower/kubernetes-the-hard-way/blob/master/docs/05-kubernetes-configuration-files.md

このLabでは各k8sコンポーネントが使用するkubeconfigを作成する。


Client Authentication Configs


Kubernetes Public IP Address

API Serverの外部公開用のIPアドレスを確認する。


コマンド

KUBERNETES_PUBLIC_ADDRESS=$(gcloud compute addresses describe kubernetes-the-hard-way \

--region $(gcloud config get-value compute/region) \
--format 'value(address)')


実行ログ

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ KUBERNETES_PUBLIC_ADDRESS=$(gcloud compute addresses describe kubernetes-the-hard-way \
> --region $(gcloud config get-value compute/region) \
> --format 'value(address)')
sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way
$ echo $KUBERNETES_PUBLIC_ADDRESS
35.243.101.236
sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way
$


The kubelet Kubernetes Configuration File

Kubelet用のkubeconfigを作成する。KubeletはCN=system:node:<nodeName>と設定されたクライアント証明書を使うことでノード認可をする。ノード認可を行うために、あとでAPI Serverは--authorization-mode=Nodeとして起動する。

(参考)

Using Node Authorization


コマンド

for instance in worker-0 worker-1 worker-2; do

kubectl config set-cluster kubernetes-the-hard-way \
--certificate-authority=ca.pem \
--embed-certs=true \
--server=https://${KUBERNETES_PUBLIC_ADDRESS}:6443 \
--kubeconfig=${instance}.kubeconfig

kubectl config set-credentials system:node:${instance} \
--client-certificate=${instance}.pem \
--client-key=${instance}-key.pem \
--embed-certs=true \
--kubeconfig=${instance}.kubeconfig

kubectl config set-context default \
--cluster=kubernetes-the-hard-way \
--user=system:node:${instance} \
--kubeconfig=${instance}.kubeconfig

kubectl config use-context default --kubeconfig=${instance}.kubeconfig
done



実行ログ

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ for instance in worker-0 worker-1 worker-2; do
> kubectl config set-cluster kubernetes-the-hard-way \
> --certificate-authority=ca.pem \
> --embed-certs=true \
> --server=https://${KUBERNETES_PUBLIC_ADDRESS}:6443 \
> --kubeconfig=${instance}.kubeconfig
>
> kubectl config set-credentials system:node:${instance} \
> --client-certificate=${instance}.pem \
> --client-key=${instance}-key.pem \
> --embed-certs=true \
> --kubeconfig=${instance}.kubeconfig
>
> kubectl config set-context default \
> --cluster=kubernetes-the-hard-way \
> --user=system:node:${instance} \
> --kubeconfig=${instance}.kubeconfig
>
> kubectl config use-context default --kubeconfig=${instance}.kubeconfig
> done
Cluster "kubernetes-the-hard-way" set.
User "system:node:worker-0" set.
Context "default" created.
Switched to context "default".
Cluster "kubernetes-the-hard-way" set.
User "system:node:worker-1" set.
Context "default" created.
Switched to context "default".
Cluster "kubernetes-the-hard-way" set.
User "system:node:worker-2" set.
Context "default" created.
Switched to context "default".
sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way
$

確認する。

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ cat worker-0.kubeconfig
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: <CA証明書>
server: https://35.243.101.236:6443
name: kubernetes-the-hard-way
contexts:
- context:
cluster: kubernetes-the-hard-way
user: system:node:worker-0
name: default
current-context: default
kind: Config
preferences: {}
users:
- name: system:node:worker-0
user:
client-certificate-data: <Kubeletのクライアント証明書>
client-key-data: <Kubeletの秘密鍵>
sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way
$

証明書や秘密鍵のデータはbase64エンコードされている。base64 -Dで戻して確認することができる。

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ cat worker-0.kubeconfig | grep certificate-authority-data | awk '{print $2}' | base64 -D
-----BEGIN CERTIFICATE-----
MIIDoDCCAoigAwIBAgIUeMrpBsn7BQzXJJ7oz5+9XPurM6UwDQYJKoZIhvcNAQEL
BQAwaDELMAkGA1UEBhMCVVMxDzANBgNVBAgTBk9yZWdvbjERMA8GA1UEBxMIUG9y
dGxhbmQxEzARBgNVBAoTCkt1YmVybmV0ZXMxCzAJBgNVBAsTAkNBMRMwEQYDVQQD
EwpLdWJlcm5ldGVzMB4XDTE4MTExMTA0MTIwMFoXDTIzMTExMDA0MTIwMFowaDEL
MAkGA1UEBhMCVVMxDzANBgNVBAgTBk9yZWdvbjERMA8GA1UEBxMIUG9ydGxhbmQx
EzARBgNVBAoTCkt1YmVybmV0ZXMxCzAJBgNVBAsTAkNBMRMwEQYDVQQDEwpLdWJl
cm5ldGVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1mOweOZlxEvV
HcpA2T0G0LC58yqgzAj9M27QB9FOUIFTRRYmdZ3QlGKM2TaHUwMVMBLobh3EUrp9
e6ThAh1Tc2S/NsSTbmXpVlx4kHiJKAJK6M/srLFE3r6gWDdKsMh7o0AVmylVn9M0
bQrJ0vg2gbFXNaD0aXpYVFWPlxhqeZrf7nAgx6R7Kl5US4rlZ3Pyn8UMNLBDsGWC
QFcmdFOP8aV8zIjsDwyeVwjTOIzNo8DSBnrYu+z0zDkgUKccp+HgNt/7SLW7u4Zq
d2gHjVXfIrlwzikZ69IcCCg5YdvH8A9exObCDzYgj7Pi+0bn1qa3+P2jrkcJch+0
ERMAAK8SVwIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
/zAdBgNVHQ4EFgQUhdE6ktI5OtKwCPAtnjGpf9tIUMQwDQYJKoZIhvcNAQELBQAD
ggEBAGoGeJdYdAYZ9frfK+KBAu5QQyYh56u6UxZfHgqJ4NNIo2sM1YYX1EP6LPKI
TnsYzDw5t+XzN1twrgCazjQjR6Hus0iv5R4eTQprL65vbaPpUSD+x8FkJ6V8X6cJ
go4xPUUp4dfq3JY27dqdFyKBPcNme6j4TCxZiCAnro8v8X7dVLbvWoSe2QxPuw05
l4j4Hk/Cwl8yCmK1GNL7q9OW3VaImTN2KbUuhQrpqN9BM3wOwdiOrW/BnodMY2QD
pwh5TEV6TDDpDSlM85jXfL2No7wQXFReZVQ0P1wEk5kLx0A5HmRK3HpqnkLXGSE6
AMekXv0nLbGEcMYlIZgluubFgPw=
-----END CERTIFICATE-----
sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way
$


The kube-proxy Kubernetes Configuration File

Kube Proxy用のkubeconfigを作成する。


コマンド

{

kubectl config set-cluster kubernetes-the-hard-way \
--certificate-authority=ca.pem \
--embed-certs=true \
--server=https://${KUBERNETES_PUBLIC_ADDRESS}:6443 \
--kubeconfig=kube-proxy.kubeconfig

kubectl config set-credentials system:kube-proxy \
--client-certificate=kube-proxy.pem \
--client-key=kube-proxy-key.pem \
--embed-certs=true \
--kubeconfig=kube-proxy.kubeconfig

kubectl config set-context default \
--cluster=kubernetes-the-hard-way \
--user=system:kube-proxy \
--kubeconfig=kube-proxy.kubeconfig

kubectl config use-context default --kubeconfig=kube-proxy.kubeconfig
}



実行ログ

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ {
> kubectl config set-cluster kubernetes-the-hard-way \
> --certificate-authority=ca.pem \
> --embed-certs=true \
> --server=https://${KUBERNETES_PUBLIC_ADDRESS}:6443 \
> --kubeconfig=kube-proxy.kubeconfig
>
> kubectl config set-credentials system:kube-proxy \
> --client-certificate=kube-proxy.pem \
> --client-key=kube-proxy-key.pem \
> --embed-certs=true \
> --kubeconfig=kube-proxy.kubeconfig
>
> kubectl config set-context default \
> --cluster=kubernetes-the-hard-way \
> --user=system:kube-proxy \
> --kubeconfig=kube-proxy.kubeconfig
>
> kubectl config use-context default --kubeconfig=kube-proxy.kubeconfig
> }
Cluster "kubernetes-the-hard-way" set.
User "system:kube-proxy" set.
Context "default" created.
Switched to context "default".
sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way
$


The kube-controller-manager Kubernetes Configuration File

Controller Manager用のkubeconfigを作成する。接続先はAPIサーバーの外部公開用のIPアドレスではなく127.0.0.1を指定している。3台のAPI Serverは対等でありリーダーがいるわけではないので、同居しているAPI Serverに接続するようにしているが、外部公開用のIPアドレスを使用したとしても問題ないはず。


コマンド

{

kubectl config set-cluster kubernetes-the-hard-way \
--certificate-authority=ca.pem \
--embed-certs=true \
--server=https://127.0.0.1:6443 \
--kubeconfig=kube-controller-manager.kubeconfig

kubectl config set-credentials system:kube-controller-manager \
--client-certificate=kube-controller-manager.pem \
--client-key=kube-controller-manager-key.pem \
--embed-certs=true \
--kubeconfig=kube-controller-manager.kubeconfig

kubectl config set-context default \
--cluster=kubernetes-the-hard-way \
--user=system:kube-controller-manager \
--kubeconfig=kube-controller-manager.kubeconfig

kubectl config use-context default --kubeconfig=kube-controller-manager.kubeconfig
}



実行ログ

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ {
> kubectl config set-cluster kubernetes-the-hard-way \
> --certificate-authority=ca.pem \
> --embed-certs=true \
> --server=https://127.0.0.1:6443 \
> --kubeconfig=kube-controller-manager.kubeconfig
>
> kubectl config set-credentials system:kube-controller-manager \
> --client-certificate=kube-controller-manager.pem \
> --client-key=kube-controller-manager-key.pem \
> --embed-certs=true \
> --kubeconfig=kube-controller-manager.kubeconfig
>
> kubectl config set-context default \
> --cluster=kubernetes-the-hard-way \
> --user=system:kube-controller-manager \
> --kubeconfig=kube-controller-manager.kubeconfig
>
> kubectl config use-context default --kubeconfig=kube-controller-manager.kubeconfig
> }
Cluster "kubernetes-the-hard-way" set.
User "system:kube-controller-manager" set.
Context "default" created.
Switched to context "default".
sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way
$


The kube-scheduler Kubernetes Configuration File

Scheduler用のkubeconfigを作成する。こちらも接続先はAPIサーバーの外部公開用のIPアドレスではなく127.0.0.1を指定している。


コマンド

{

kubectl config set-cluster kubernetes-the-hard-way \
--certificate-authority=ca.pem \
--embed-certs=true \
--server=https://127.0.0.1:6443 \
--kubeconfig=kube-scheduler.kubeconfig

kubectl config set-credentials system:kube-scheduler \
--client-certificate=kube-scheduler.pem \
--client-key=kube-scheduler-key.pem \
--embed-certs=true \
--kubeconfig=kube-scheduler.kubeconfig

kubectl config set-context default \
--cluster=kubernetes-the-hard-way \
--user=system:kube-scheduler \
--kubeconfig=kube-scheduler.kubeconfig

kubectl config use-context default --kubeconfig=kube-scheduler.kubeconfig
}



実行ログ

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ {
> kubectl config set-cluster kubernetes-the-hard-way \
> --certificate-authority=ca.pem \
> --embed-certs=true \
> --server=https://127.0.0.1:6443 \
> --kubeconfig=kube-scheduler.kubeconfig
>
> kubectl config set-credentials system:kube-scheduler \
> --client-certificate=kube-scheduler.pem \
> --client-key=kube-scheduler-key.pem \
> --embed-certs=true \
> --kubeconfig=kube-scheduler.kubeconfig
>
> kubectl config set-context default \
> --cluster=kubernetes-the-hard-way \
> --user=system:kube-scheduler \
> --kubeconfig=kube-scheduler.kubeconfig
>
> kubectl config use-context default --kubeconfig=kube-scheduler.kubeconfig
> }
Cluster "kubernetes-the-hard-way" set.
User "system:kube-scheduler" set.
Context "default" created.
Switched to context "default".
sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way
$


The admin Kubernetes Configuration File

adminユーザー用の設定ファイルを作成する。外部公開用のIPアドレスではなく127.0.0.1を指定しているが、Masterノードに配置してMasterノードでkubectlを実行することを想定しているため。作業用PCで使用するkubeconfigはまたあとで作成するが、そのときはAPI Serverの外部公開用のIPアドレスを指定する。


コマンド

{

kubectl config set-cluster kubernetes-the-hard-way \
--certificate-authority=ca.pem \
--embed-certs=true \
--server=https://127.0.0.1:6443 \
--kubeconfig=admin.kubeconfig

kubectl config set-credentials admin \
--client-certificate=admin.pem \
--client-key=admin-key.pem \
--embed-certs=true \
--kubeconfig=admin.kubeconfig

kubectl config set-context default \
--cluster=kubernetes-the-hard-way \
--user=admin \
--kubeconfig=admin.kubeconfig

kubectl config use-context default --kubeconfig=admin.kubeconfig
}



実行ログ

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ {
> kubectl config set-cluster kubernetes-the-hard-way \
> --certificate-authority=ca.pem \
> --embed-certs=true \
> --server=https://127.0.0.1:6443 \
> --kubeconfig=admin.kubeconfig
>
> kubectl config set-credentials admin \
> --client-certificate=admin.pem \
> --client-key=admin-key.pem \
> --embed-certs=true \
> --kubeconfig=admin.kubeconfig
>
> kubectl config set-context default \
> --cluster=kubernetes-the-hard-way \
> --user=admin \
> --kubeconfig=admin.kubeconfig
>
> kubectl config use-context default --kubeconfig=admin.kubeconfig
> }
Cluster "kubernetes-the-hard-way" set.
User "admin" set.
Context "default" created.
Switched to context "default".
sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way
$


Distribute the Kubernetes Configuration Files

作成したkubeconfigは以下。

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ ls -l *.kubeconfig
-rw------- 1 sotoiwa staff 6265 11 11 16:47 admin.kubeconfig
-rw------- 1 sotoiwa staff 6391 11 11 16:37 kube-controller-manager.kubeconfig
-rw------- 1 sotoiwa staff 6326 11 11 16:17 kube-proxy.kubeconfig
-rw------- 1 sotoiwa staff 6341 11 11 16:44 kube-scheduler.kubeconfig
-rw------- 1 sotoiwa staff 6388 11 11 16:04 worker-0.kubeconfig
-rw------- 1 sotoiwa staff 6388 11 11 16:04 worker-1.kubeconfig
-rw------- 1 sotoiwa staff 6388 11 11 16:04 worker-2.kubeconfig
sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way
$

Workerノードにkubeletkube-proxyのkubeconfigを配布する。

for instance in worker-0 worker-1 worker-2; do

gcloud compute scp ${instance}.kubeconfig kube-proxy.kubeconfig ${instance}:~/
done

Masterノードにadminkube-controller-managerkube-schedulerのkubeconfigを配布する。

for instance in controller-0 controller-1 controller-2; do

gcloud compute scp admin.kubeconfig kube-controller-manager.kubeconfig kube-scheduler.kubeconfig ${instance}:~/
done


Generating the Data Encryption Config and Key

このLabではSecretを暗号化してからetcdに保存するための鍵と設定ファイルを作成する。

(参考)

Encrypting Secret Data at Rest


The Encryption Key

暗号化キーを作成する。

ENCRYPTION_KEY=$(head -c 32 /dev/urandom | base64)


The Encryption Config File

設定ファイルを作成する。

cat > encryption-config.yaml <<EOF

kind: EncryptionConfig
apiVersion: v1
resources:
- resources:
- secrets
providers:
- aescbc:
keys:
- name: key1
secret: ${ENCRYPTION_KEY}
- identity: {}
EOF

作成したファイルをMasterノードに転送する。

for instance in controller-0 controller-1 controller-2; do

gcloud compute scp encryption-config.yaml ${instance}:~/
done


Bootstrapping the etcd Cluster

https://github.com/kelseyhightower/kubernetes-the-hard-way/blob/master/docs/07-bootstrapping-etcd.md

このLabではetcdクラスターを起動する。


Prerequisites

このLabでのコマンドはcontroller-0controller-1controller-2のそれぞれのノードで実行する。ノードへのログインは以下のコマンド。

gcloud compute ssh controller-0


Running commands in parallel with tmux

(最初のLabでも記載があった内容なので省略)


Bootstrapping an etcd Cluster Member


Download and Install the etcd Binaries

etcdのバイナリをダウンロードする。バイナリのダウンロード元は以下のリリースページ。バージョンはv3.3.9をダウンロードしている。

https://github.com/etcd-io/etcd/releases

wget -q --show-progress --https-only --timestamping \

"https://github.com/coreos/etcd/releases/download/v3.3.9/etcd-v3.3.9-linux-amd64.tar.gz"

ダウンロードしたファイルを展開して/usr/local/binディレクトリーにインストールする。

{

tar -xvf etcd-v3.3.9-linux-amd64.tar.gz
sudo mv etcd-v3.3.9-linux-amd64/etcd* /usr/local/bin/
}


Configure the etcd Server

/etc/etcd/var/lib/etcdディレクトリーを作成して以下のファイルをコピーする。


  • CA証明書

  • APIサーバーの秘密鍵と証明書

{

sudo mkdir -p /etc/etcd /var/lib/etcd
sudo cp ca.pem kubernetes-key.pem kubernetes.pem /etc/etcd/
}

現在のVMインスタンス自身のIPアドレスを取得して変数に入れる。


コマンド

INTERNAL_IP=$(curl -s -H "Metadata-Flavor: Google" \

http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/0/ip)


実行ログ

sotoiwa@controller-0:~$ INTERNAL_IP=$(curl -s -H "Metadata-Flavor: Google" \

> http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/0/ip)
sotoiwa@controller-0:~$ echo $INTERNAL_IP
10.240.0.10
sotoiwa@controller-0:~$

Etcdメンバーはユニークな名前を持つ必要があるので、名前としてインスタンス名を使う。-sは短い形式(最初のドットまで)のホスト名を表示するオプション。


コマンド

ETCD_NAME=$(hostname -s)



実行ログ

sotoiwa@controller-0:~$ ETCD_NAME=$(hostname -s)

sotoiwa@controller-0:~$ echo $ETCD_NAME
controller-0
sotoiwa@controller-0:~$

Systemdサービスの定義ファイルetcd.serviceを作成する。etcdの引数として指定しているものについては以下のドキュメントに解説がある。

(参考)

Operating etcd clusters for Kubernetes


コマンド

cat <<EOF | sudo tee /etc/systemd/system/etcd.service

[Unit]
Description=etcd
Documentation=https://github.com/coreos

[Service]
ExecStart=/usr/local/bin/etcd \\
--name ${ETCD_NAME} \\
--cert-file=/etc/etcd/kubernetes.pem \\
--key-file=/etc/etcd/kubernetes-key.pem \\
--peer-cert-file=/etc/etcd/kubernetes.pem \\
--peer-key-file=/etc/etcd/kubernetes-key.pem \\
--trusted-ca-file=/etc/etcd/ca.pem \\
--peer-trusted-ca-file=/etc/etcd/ca.pem \\
--peer-client-cert-auth \\
--client-cert-auth \\
--initial-advertise-peer-urls https://${INTERNAL_IP}:2380 \\
--listen-peer-urls https://${INTERNAL_IP}:2380 \\
--listen-client-urls https://${INTERNAL_IP}:2379,https://127.0.0.1:2379 \\
--advertise-client-urls https://${INTERNAL_IP}:2379 \\
--initial-cluster-token etcd-cluster-0 \\
--initial-cluster controller-0=https://10.240.0.10:2380,controller-1=https://10.240.0.11:2380,controller-2=https://10.240.0.12:2380 \\
--initial-cluster-state new \\
--data-dir=/var/lib/etcd
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF



実行ログ

sotoiwa@controller-0:~$ cat <<EOF | sudo tee /etc/systemd/system/etcd.service

> [Unit]
> Description=etcd
> Documentation=https://github.com/coreos
>
> [Service]
> ExecStart=/usr/local/bin/etcd \\
> --name ${ETCD_NAME} \\
> --cert-file=/etc/etcd/kubernetes.pem \\
> --key-file=/etc/etcd/kubernetes-key.pem \\
> --peer-cert-file=/etc/etcd/kubernetes.pem \\
> --peer-key-file=/etc/etcd/kubernetes-key.pem \\
> --trusted-ca-file=/etc/etcd/ca.pem \\
> --peer-trusted-ca-file=/etc/etcd/ca.pem \\
> --peer-client-cert-auth \\
> --client-cert-auth \\
> --initial-advertise-peer-urls https://${INTERNAL_IP}:2380 \\
> --listen-peer-urls https://${INTERNAL_IP}:2380 \\
> --listen-client-urls https://${INTERNAL_IP}:2379,https://127.0.0.1:2379 \\
> --advertise-client-urls https://${INTERNAL_IP}:2379 \\
> --initial-cluster-token etcd-cluster-0 \\
> --initial-cluster controller-0=https://10.240.0.10:2380,controller-1=https://10.240.0.11:2380,controller-2=https://10.240.0.12:2380 \\
> --initial-cluster-state new \\
> --data-dir=/var/lib/etcd
> Restart=on-failure
> RestartSec=5
>
> [Install]
> WantedBy=multi-user.target
> EOF
[Unit]
Description=etcd
Documentation=https://github.com/coreos

[Service]
ExecStart=/usr/local/bin/etcd \
--name controller-0 \
--cert-file=/etc/etcd/kubernetes.pem \
--key-file=/etc/etcd/kubernetes-key.pem \
--peer-cert-file=/etc/etcd/kubernetes.pem \
--peer-key-file=/etc/etcd/kubernetes-key.pem \
--trusted-ca-file=/etc/etcd/ca.pem \
--peer-trusted-ca-file=/etc/etcd/ca.pem \
--peer-client-cert-auth \
--client-cert-auth \
--initial-advertise-peer-urls https://10.240.0.10:2380 \
--listen-peer-urls https://10.240.0.10:2380 \
--listen-client-urls https://10.240.0.10:2379,https://127.0.0.1:2379 \
--advertise-client-urls https://10.240.0.10:2379 \
--initial-cluster-token etcd-cluster-0 \
--initial-cluster controller-0=https://10.240.0.10:2380,controller-1=https://10.240.0.11:2380,controller-2=https://10.240.0.12:2380 \
--initial-cluster-state new \
--data-dir=/var/lib/etcd
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
sotoiwa@controller-0:~$




  • --cert-file--key-fileがサーバーとしての通信に使う証明書と秘密鍵


  • --peer-cert-file--peer-key-fileはetcd間の通信に使う証明書と秘密鍵

  • API Server用に作成した秘密鍵や証明書をetcdでも使用している


  • --peer-client-cert-auth--client-cert-authが指定されているので、サーバーとしての通信でもetcd間の通信でもクライアント認証する


Start the etcd Server

etcdを起動する。

{

sudo systemctl daemon-reload
sudo systemctl enable etcd
sudo systemctl start etcd
}

サービスのステータスを確認。

sudo systemctl status etcd


Verification

etcdクラスターのメンバーをリストするコマンドを実行する。


コマンド

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


実行ログ

sotoiwa@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
f98dc20bce6225a0, started, controller-0, https://10.240.0.10:2380, https://10.240.0.10:2379
ffed16798470cab5, started, controller-1, https://10.240.0.11:2380, https://10.240.0.11:2379
sotoiwa@controller-0:~$


Bootstrapping the Kubernetes Control Plane

https://github.com/kelseyhightower/kubernetes-the-hard-way/blob/master/docs/08-bootstrapping-kubernetes-controllers.md

このLabではMasterノードのk8sコンポーネント(apiserver、scheduler、controller-manager)を起動する。


Prerequisites

前のLabと同じく、このLabのコマンドは全てのMasterノードで実施する必要がある。


Running commands in parallel with tmux

(省略)


Provision the Kubernetes Control Plane

Kubenetesの構成ファイル用ディレクトリーを作成する。

sudo mkdir -p /etc/kubernetes/config


Download and Install the Kubernetes Controller Binaries

公式のバイナリをダウンロードする。この直接ダウンロードリンクにどうやってたどり着けばいいのかわからなかった。以下のリリースページからtarをダウンロードできる。tarの中にはバイナリは入っておらず、解凍してkubernetes/cluster/get-kube-binaries.shを実行するとダウンロードできる。バージョンはv1.12.0をダウンロードする。

https://github.com/kubernetes/kubernetes/releases

wget -q --show-progress --https-only --timestamping \

"https://storage.googleapis.com/kubernetes-release/release/v1.12.0/bin/linux/amd64/kube-apiserver" \
"https://storage.googleapis.com/kubernetes-release/release/v1.12.0/bin/linux/amd64/kube-controller-manager" \
"https://storage.googleapis.com/kubernetes-release/release/v1.12.0/bin/linux/amd64/kube-scheduler" \
"https://storage.googleapis.com/kubernetes-release/release/v1.12.0/bin/linux/amd64/kubectl"

バイナリを/usr/local/binディレクトリーにインストールする。

{

chmod +x kube-apiserver kube-controller-manager kube-scheduler kubectl
sudo mv kube-apiserver kube-controller-manager kube-scheduler kubectl /usr/local/bin/
}

確認する。

sotoiwa@controller-0:~$ ls -l /usr/local/bin/

total 493164
-rwxr-xr-x 1 sotoiwa sotoiwa 18934016 Jul 24 17:13 etcd
-rwxr-xr-x 1 sotoiwa sotoiwa 15809280 Jul 24 17:13 etcdctl
-rwxrwxr-x 1 sotoiwa sotoiwa 192766426 Sep 27 23:04 kube-apiserver
-rwxrwxr-x 1 sotoiwa sotoiwa 162936572 Sep 27 23:04 kube-controller-manager
-rwxrwxr-x 1 sotoiwa sotoiwa 57180560 Sep 27 23:04 kube-scheduler
-rwxrwxr-x 1 sotoiwa sotoiwa 57343669 Sep 27 23:04 kubectl
sotoiwa@controller-0:~$


Configure the Kubernetes API Server

/var/lib/kubernetes/ディレクトリーを作成して以下のファイルを移動する。


  • CAの秘密鍵と証明書

  • API Serverの秘密鍵と証明書

  • Service Account作成用の秘密鍵と証明書

  • Secretの暗号化用の設定ファイル

{

sudo mkdir -p /var/lib/kubernetes/

sudo mv ca.pem ca-key.pem kubernetes-key.pem kubernetes.pem \
service-account-key.pem service-account.pem \
encryption-config.yaml /var/lib/kubernetes/
}

確認する。

sotoiwa@controller-2:~$ ls -l /var/lib/kubernetes/

total 28
-rw------- 1 sotoiwa sotoiwa 1675 Nov 11 06:04 ca-key.pem
-rw-r--r-- 1 sotoiwa sotoiwa 1318 Nov 11 06:04 ca.pem
-rw-r--r-- 1 sotoiwa sotoiwa 196 Nov 11 08:09 encryption-config.yaml
-rw------- 1 sotoiwa sotoiwa 1679 Nov 11 06:04 kubernetes-key.pem
-rw-r--r-- 1 sotoiwa sotoiwa 1521 Nov 11 06:04 kubernetes.pem
-rw------- 1 sotoiwa sotoiwa 1679 Nov 11 06:04 service-account-key.pem
-rw-r--r-- 1 sotoiwa sotoiwa 1440 Nov 11 06:04 service-account.pem
sotoiwa@controller-2:~$

現在のVMインスタンス自身のIPアドレスを取得して変数に入れる。

INTERNAL_IP=$(curl -s -H "Metadata-Flavor: Google" \

http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/0/ip)

Systemdサービスの定義ファイルkube-apiserver.serviceを作成する。引数については以下のリンク先に説明がある。

(参考)

kube-apiserver


コマンド

cat <<EOF | sudo tee /etc/systemd/system/kube-apiserver.service

[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/kubernetes/kubernetes

[Service]
ExecStart=/usr/local/bin/kube-apiserver \\
--advertise-address=${INTERNAL_IP} \\
--allow-privileged=true \\
--apiserver-count=3 \\
--audit-log-maxage=30 \\
--audit-log-maxbackup=3 \\
--audit-log-maxsize=100 \\
--audit-log-path=/var/log/audit.log \\
--authorization-mode=Node,RBAC \\
--bind-address=0.0.0.0 \\
--client-ca-file=/var/lib/kubernetes/ca.pem \\
--enable-admission-plugins=Initializers,NamespaceLifecycle,NodeRestriction,LimitRanger,ServiceAccount,DefaultStorageClass,ResourceQuota \\
--enable-swagger-ui=true \\
--etcd-cafile=/var/lib/kubernetes/ca.pem \\
--etcd-certfile=/var/lib/kubernetes/kubernetes.pem \\
--etcd-keyfile=/var/lib/kubernetes/kubernetes-key.pem \\
--etcd-servers=https://10.240.0.10:2379,https://10.240.0.11:2379,https://10.240.0.12:2379 \\
--event-ttl=1h \\
--experimental-encryption-provider-config=/var/lib/kubernetes/encryption-config.yaml \\
--kubelet-certificate-authority=/var/lib/kubernetes/ca.pem \\
--kubelet-client-certificate=/var/lib/kubernetes/kubernetes.pem \\
--kubelet-client-key=/var/lib/kubernetes/kubernetes-key.pem \\
--kubelet-https=true \\
--runtime-config=api/all \\
--service-account-key-file=/var/lib/kubernetes/service-account.pem \\
--service-cluster-ip-range=10.32.0.0/24 \\
--service-node-port-range=30000-32767 \\
--tls-cert-file=/var/lib/kubernetes/kubernetes.pem \\
--tls-private-key-file=/var/lib/kubernetes/kubernetes-key.pem \\
--v=2
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF



実行ログ

sotoiwa@controller-0:~$ cat <<EOF | sudo tee /etc/systemd/system/kube-apiserver.service

> [Unit]
> Description=Kubernetes API Server
> Documentation=https://github.com/kubernetes/kubernetes
>
> [Service]
> ExecStart=/usr/local/bin/kube-apiserver \\
> --advertise-address=${INTERNAL_IP} \\
> --allow-privileged=true \\
> --apiserver-count=3 \\
> --audit-log-maxage=30 \\
> --audit-log-maxbackup=3 \\
> --audit-log-maxsize=100 \\
> --audit-log-path=/var/log/audit.log \\
> --authorization-mode=Node,RBAC \\
> --bind-address=0.0.0.0 \\
> --client-ca-file=/var/lib/kubernetes/ca.pem \\
> --enable-admission-plugins=Initializers,NamespaceLifecycle,NodeRestriction,LimitRanger,ServiceAccount,DefaultStorageClass,ResourceQuota \\
> --enable-swagger-ui=true \\
> --etcd-cafile=/var/lib/kubernetes/ca.pem \\
> --etcd-certfile=/var/lib/kubernetes/kubernetes.pem \\
> --etcd-keyfile=/var/lib/kubernetes/kubernetes-key.pem \\
> --etcd-servers=https://10.240.0.10:2379,https://10.240.0.11:2379,https://10.240.0.12:2379 \\
> --event-ttl=1h \\
> --experimental-encryption-provider-config=/var/lib/kubernetes/encryption-config.yaml \\
> --kubelet-certificate-authority=/var/lib/kubernetes/ca.pem \\
> --kubelet-client-certificate=/var/lib/kubernetes/kubernetes.pem \\
> --kubelet-client-key=/var/lib/kubernetes/kubernetes-key.pem \\
> --kubelet-https=true \\
> --runtime-config=api/all \\
> --service-account-key-file=/var/lib/kubernetes/service-account.pem \\
> --service-cluster-ip-range=10.32.0.0/24 \\
> --service-node-port-range=30000-32767 \\
> --tls-cert-file=/var/lib/kubernetes/kubernetes.pem \\
> --tls-private-key-file=/var/lib/kubernetes/kubernetes-key.pem \\
> --v=2
> Restart=on-failure
> RestartSec=5
>
> [Install]
> WantedBy=multi-user.target
> EOF
[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/kubernetes/kubernetes

[Service]
ExecStart=/usr/local/bin/kube-apiserver \
--advertise-address=10.240.0.10 \
--allow-privileged=true \
--apiserver-count=3 \
--audit-log-maxage=30 \
--audit-log-maxbackup=3 \
--audit-log-maxsize=100 \
--audit-log-path=/var/log/audit.log \
--authorization-mode=Node,RBAC \
--bind-address=0.0.0.0 \
--client-ca-file=/var/lib/kubernetes/ca.pem \
--enable-admission-plugins=Initializers,NamespaceLifecycle,NodeRestriction,LimitRanger,ServiceAccount,DefaultStorageClass,ResourceQuota \
--enable-swagger-ui=true \
--etcd-cafile=/var/lib/kubernetes/ca.pem \
--etcd-certfile=/var/lib/kubernetes/kubernetes.pem \
--etcd-keyfile=/var/lib/kubernetes/kubernetes-key.pem \
--etcd-servers=https://10.240.0.10:2379,https://10.240.0.11:2379,https://10.240.0.12:2379 \
--event-ttl=1h \
--experimental-encryption-provider-config=/var/lib/kubernetes/encryption-config.yaml \
--kubelet-certificate-authority=/var/lib/kubernetes/ca.pem \
--kubelet-client-certificate=/var/lib/kubernetes/kubernetes.pem \
--kubelet-client-key=/var/lib/kubernetes/kubernetes-key.pem \
--kubelet-https=true \
--runtime-config=api/all \
--service-account-key-file=/var/lib/kubernetes/service-account.pem \
--service-cluster-ip-range=10.32.0.0/24 \
--service-node-port-range=30000-32767 \
--tls-cert-file=/var/lib/kubernetes/kubernetes.pem \
--tls-private-key-file=/var/lib/kubernetes/kubernetes-key.pem \
--v=2
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
sotoiwa@controller-0:~$




  • --authorization-mode=Node,RBACとしており、Kubeletはノード認可する


  • --etcd-***がetcdとの接続に関する設定で使用する証明書などを指定している


  • --kubelet-***がkubeletとの接続に関する設定で使用する証明書などを指定している


  • --tls-cert-file--tls-private-key-fileが自身がHTTPSサーバーとしてリクエストを受け付けるための設定


  • --service-cluster-ip-range=10.32.0.0/24でServiceが使用するIPのCIDRを指定している


Configure the Kubernetes Controller Manager

Controller Managerが使用するkubeconfigを/var/lib/kubernetes/に配置する。

sudo mv kube-controller-manager.kubeconfig /var/lib/kubernetes/

Systemdサービスの定義ファイルkube-controller-manager.serviceを作成する。

(参考)

kube-controller-manager


コマンド

cat <<EOF | sudo tee /etc/systemd/system/kube-controller-manager.service

[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/kubernetes/kubernetes

[Service]
ExecStart=/usr/local/bin/kube-controller-manager \\
--address=0.0.0.0 \\
--cluster-cidr=10.200.0.0/16 \\
--cluster-name=kubernetes \\
--cluster-signing-cert-file=/var/lib/kubernetes/ca.pem \\
--cluster-signing-key-file=/var/lib/kubernetes/ca-key.pem \\
--kubeconfig=/var/lib/kubernetes/kube-controller-manager.kubeconfig \\
--leader-elect=true \\
--root-ca-file=/var/lib/kubernetes/ca.pem \\
--service-account-private-key-file=/var/lib/kubernetes/service-account-key.pem \\
--service-cluster-ip-range=10.32.0.0/24 \\
--use-service-account-credentials=true \\
--v=2
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF



実行ログ

sotoiwa@controller-0:~$ cat <<EOF | sudo tee /etc/systemd/system/kube-controller-manager.service

> [Unit]
> Description=Kubernetes Controller Manager
> Documentation=https://github.com/kubernetes/kubernetes
>
> [Service]
> ExecStart=/usr/local/bin/kube-controller-manager \\
> --address=0.0.0.0 \\
> --cluster-cidr=10.200.0.0/16 \\
> --cluster-name=kubernetes \\
> --cluster-signing-cert-file=/var/lib/kubernetes/ca.pem \\
> --cluster-signing-key-file=/var/lib/kubernetes/ca-key.pem \\
> --kubeconfig=/var/lib/kubernetes/kube-controller-manager.kubeconfig \\
> --leader-elect=true \\
> --root-ca-file=/var/lib/kubernetes/ca.pem \\
> --service-account-private-key-file=/var/lib/kubernetes/service-account-key.pem \\
> --service-cluster-ip-range=10.32.0.0/24 \\
> --use-service-account-credentials=true \\
> --v=2
> Restart=on-failure
> RestartSec=5
>
> [Install]
> WantedBy=multi-user.target
> EOF
[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/kubernetes/kubernetes

[Service]
ExecStart=/usr/local/bin/kube-controller-manager \
--address=0.0.0.0 \
--cluster-cidr=10.200.0.0/16 \
--cluster-name=kubernetes \
--cluster-signing-cert-file=/var/lib/kubernetes/ca.pem \
--cluster-signing-key-file=/var/lib/kubernetes/ca-key.pem \
--kubeconfig=/var/lib/kubernetes/kube-controller-manager.kubeconfig \
--leader-elect=true \
--root-ca-file=/var/lib/kubernetes/ca.pem \
--service-account-private-key-file=/var/lib/kubernetes/service-account-key.pem \
--service-cluster-ip-range=10.32.0.0/24 \
--use-service-account-credentials=true \
--v=2
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
sotoiwa@controller-0:~$




  • --cluster-cidr=10.200.0.0/16でクラスターのCIDRを指定している


  • --kubeconfigでAPI Serverへの接続情報を指定している


  • --service-account-private-key-fileでServiec Account Tokenの作成に使用する秘密鍵を指定している


  • --service-cluster-ip-range=10.32.0.0/24でAPI Serverと同じくServiceのCIDRを指定している


  • --leader-elect=trueを設定しているので、3台のMasterノードのうちの1つがリーダーになる


  • --cluster-signing-key-file--cluster-signing-cert-fileを指定しているのは証明書のローテーション時にController Managerが署名を行うためと思われる


Configure the Kubernetes Scheduler

Schedulerが使用するkubeconfigを/var/lib/kubernetes/に配置する。

sudo mv kube-scheduler.kubeconfig /var/lib/kubernetes/

Schedulerの設定ファイルkube-scheduler.yamlを作成する。


コマンド

cat <<EOF | sudo tee /etc/kubernetes/config/kube-scheduler.yaml

apiVersion: componentconfig/v1alpha1
kind: KubeSchedulerConfiguration
clientConnection:
kubeconfig: "/var/lib/kubernetes/kube-scheduler.kubeconfig"
leaderElection:
leaderElect: true
EOF


実行ログ

sotoiwa@controller-0:~$ cat <<EOF | sudo tee /etc/kubernetes/config/kube-scheduler.yaml

> apiVersion: componentconfig/v1alpha1
> kind: KubeSchedulerConfiguration
> clientConnection:
> kubeconfig: "/var/lib/kubernetes/kube-scheduler.kubeconfig"
> leaderElection:
> leaderElect: true
> EOF
apiVersion: componentconfig/v1alpha1
kind: KubeSchedulerConfiguration
clientConnection:
kubeconfig: "/var/lib/kubernetes/kube-scheduler.kubeconfig"
leaderElection:
leaderElect: true
sotoiwa@controller-0:~$


  • kubeconfigをここで指定している


  • leaderElect: trueを設定しているので、3台のMasterノードのうちの1つがリーダーになる

Systemdサービスの定義ファイルkube-scheduler.serviceを作成する。

(参考)

kube-scheduler


コマンド

cat <<EOF | sudo tee /etc/systemd/system/kube-scheduler.service

[Unit]
Description=Kubernetes Scheduler
Documentation=https://github.com/kubernetes/kubernetes

[Service]
ExecStart=/usr/local/bin/kube-scheduler \\
--config=/etc/kubernetes/config/kube-scheduler.yaml \\
--v=2
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF



実行ログ

sotoiwa@controller-0:~$ cat <<EOF | sudo tee /etc/systemd/system/kube-scheduler.service

> [Unit]
> Description=Kubernetes Scheduler
> Documentation=https://github.com/kubernetes/kubernetes
>
> [Service]
> ExecStart=/usr/local/bin/kube-scheduler \\
> --config=/etc/kubernetes/config/kube-scheduler.yaml \\
> --v=2
> Restart=on-failure
> RestartSec=5
>
> [Install]
> WantedBy=multi-user.target
> EOF
[Unit]
Description=Kubernetes Scheduler
Documentation=https://github.com/kubernetes/kubernetes

[Service]
ExecStart=/usr/local/bin/kube-scheduler \
--config=/etc/kubernetes/config/kube-scheduler.yaml \
--v=2
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
sotoiwa@controller-0:~$



  • 先ほど作成したkube-scheduler.yamlを指定している


Start the Controller Services

サービスを有効にして起動する。

{

sudo systemctl daemon-reload
sudo systemctl enable kube-apiserver kube-controller-manager kube-scheduler
sudo systemctl start kube-apiserver kube-controller-manager kube-scheduler
}

サービスのステータスを確認する。

sudo systemctl status kube-apiserver kube-controller-manager kube-scheduler


Enable HTTP Health Checks

Google Network Load BalancerがAPI Serverへのリクエストを負荷分散する。API ServerはHTTPSで接続を受け付けるが、Load BalancerはHTTPしかサポートしておらずヘルスチェックが失敗してしまうため、回避策としてヘルスチェックをプロキシするnginxを動かす。nginxは80ポートで受け取ったヘルスチェックリクエストをhttps://127.0.0.1:6443/healthzへプロキシする。この/healthzエンドポイントは認証が不要。

(参考)

Network Load Balancing Concepts

nginxをインストールする。

sudo apt-get install -y nginx

設定ファイルを作成。

cat > kubernetes.default.svc.cluster.local <<EOF

server {
listen 80;
server_name kubernetes.default.svc.cluster.local;

location /healthz {
proxy_pass https://127.0.0.1:6443/healthz;
proxy_ssl_trusted_certificate /var/lib/kubernetes/ca.pem;
}
}
EOF

設定ファイルを配置してサイトを有効化する。

{

sudo mv kubernetes.default.svc.cluster.local \
/etc/nginx/sites-available/kubernetes.default.svc.cluster.local

sudo ln -s /etc/nginx/sites-available/kubernetes.default.svc.cluster.local /etc/nginx/sites-enabled/
}

サービスを再起動して有効化する。

{

sudo systemctl restart nginx
sudo systemctl enable nginx
}


Verification

コンポーネントの状態を確認する。


コマンド

kubectl get componentstatuses --kubeconfig admin.kubeconfig



実行ログ

sotoiwa@controller-0:~$ kubectl get componentstatuses --kubeconfig admin.kubeconfig

NAME STATUS MESSAGE ERROR
scheduler Healthy ok
controller-manager Healthy ok
etcd-2 Healthy {"health":"true"}
etcd-1 Healthy {"health":"true"}
etcd-0 Healthy {"health":"true"}
sotoiwa@controller-0:~$

curlでプロキシができていることを確認する。


コマンド

curl -H "Host: kubernetes.default.svc.cluster.local" -i http://127.0.0.1/healthz



実行ログ

sotoiwa@controller-0:~$ curl -H "Host: kubernetes.default.svc.cluster.local" -i http://127.0.0.1/healthz

HTTP/1.1 200 OK
Server: nginx/1.14.0 (Ubuntu)
Date: Sun, 11 Nov 2018 11:12:28 GMT
Content-Type: text/plain; charset=utf-8
Content-Length: 2
Connection: keep-alive

oksotoiwa@controller-0:~$



RBAC for Kubelet Authorization

このセクションでは、API Serverが各WorkerノードのKubelet APIにアクセスできるようにRBACを構成する。Kubelet APIにアクセスすることで、メトリックを取得したり、ログを取得したり、Pod内でコマンドを実行したりできる。

このチュートリアルでは、Kubeletの--authorization-modeWebhookに設定する。Webhookモードではkubeconfigの設定にしたがって外部に問い合わせにいくが、Kubeletは結局API Serverに問い合わせるということだと思われる。

(参考)

Authorization Overview

Webhook Mode

controller-0で作業する。

gcloud compute ssh controller-0

system:kube-apiserver-to-kubeletというClusterRoleを作成し、Kubelet APIへのアクセスを許可する。apiGroups""はcore API groupを意味する。


コマンド

cat <<EOF | kubectl apply --kubeconfig admin.kubeconfig -f -

apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
labels:
kubernetes.io/bootstrapping: rbac-defaults
name: system:kube-apiserver-to-kubelet
rules:
- apiGroups:
- ""
resources:
- nodes/proxy
- nodes/stats
- nodes/log
- nodes/spec
- nodes/metrics
verbs:
- "*"
EOF


実行ログ

sotoiwa@controller-0:~$ cat <<EOF | kubectl apply --kubeconfig admin.kubeconfig -f -

> apiVersion: rbac.authorization.k8s.io/v1beta1
> kind: ClusterRole
> metadata:
> annotations:
> rbac.authorization.kubernetes.io/autoupdate: "true"
> labels:
> kubernetes.io/bootstrapping: rbac-defaults
> name: system:kube-apiserver-to-kubelet
> rules:
> - apiGroups:
> - ""
> resources:
> - nodes/proxy
> - nodes/stats
> - nodes/log
> - nodes/spec
> - nodes/metrics
> verbs:
> - "*"
> EOF
clusterrole.rbac.authorization.k8s.io/system:kube-apiserver-to-kubelet created
sotoiwa@controller-0:~$

Kubeletに対して、API Serverはkubernetesユーザーとして--kubelet-client-certificateで指定されたクライアント証明書を使って認証を試みるのでkubernetesユーザーをsystem:kube-apiserver-to-kubeletのClusterRoleにバインドするClusterRoleBindingを作成する。


コマンド

cat <<EOF | kubectl apply --kubeconfig admin.kubeconfig -f -

apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: system:kube-apiserver
namespace: ""
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:kube-apiserver-to-kubelet
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: kubernetes
EOF


実行ログ

sotoiwa@controller-0:~$ cat <<EOF | kubectl apply --kubeconfig admin.kubeconfig -f -

> apiVersion: rbac.authorization.k8s.io/v1beta1
> kind: ClusterRoleBinding
> metadata:
> name: system:kube-apiserver
> namespace: ""
> roleRef:
> apiGroup: rbac.authorization.k8s.io
> kind: ClusterRole
> name: system:kube-apiserver-to-kubelet
> subjects:
> - apiGroup: rbac.authorization.k8s.io
> kind: User
> name: kubernetes
> EOF
clusterrolebinding.rbac.authorization.k8s.io/system:kube-apiserver created
sotoiwa@controller-0:~$


The Kubernetes Frontend Load Balancer

API Serverの前に配置される外部ロードバランサーをプロビジョニングする。


Provision a Network Load Balancer


コマンド

{

KUBERNETES_PUBLIC_ADDRESS=$(gcloud compute addresses describe kubernetes-the-hard-way \
--region $(gcloud config get-value compute/region) \
--format 'value(address)')

gcloud compute http-health-checks create kubernetes \
--description "Kubernetes Health Check" \
--host "kubernetes.default.svc.cluster.local" \
--request-path "/healthz"

gcloud compute firewall-rules create kubernetes-the-hard-way-allow-health-check \
--network kubernetes-the-hard-way \
--source-ranges 209.85.152.0/22,209.85.204.0/22,35.191.0.0/16 \
--allow tcp

gcloud compute target-pools create kubernetes-target-pool \
--http-health-check kubernetes

gcloud compute target-pools add-instances kubernetes-target-pool \
--instances controller-0,controller-1,controller-2

gcloud compute forwarding-rules create kubernetes-forwarding-rule \
--address ${KUBERNETES_PUBLIC_ADDRESS} \
--ports 6443 \
--region $(gcloud config get-value compute/region) \
--target-pool kubernetes-target-pool
}



実行ログ

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ {
KUBERNETES_PUBLIC_ADDRESS=$(gcloud compute addresses describe kubernetes-the-hard-way \
--region $(gcloud config get-value compute/region) \
--format 'value(address)')

gcloud compute http-health-checks create kubernetes \
--description "Kubernetes Health Check" \
--host "kubernetes.default.svc.cluster.local" \
--request-path "/healthz"

gcloud compute firewall-rules create kubernetes-the-hard-way-allow-health-check \
--network kubernetes-the-hard-way \
--source-ranges 209.85.152.0/22,209.85.204.0/22,35.191.0.0/16 \
--allow tcp

gcloud compute target-pools create kubernetes-target-pool \
--http-health-check kubernetes

gcloud compute target-pools add-instances kubernetes-target-pool \
--instances controller-0,controller-1,controller-2

gcloud compute forwarding-rules create kubernetes-forwarding-rule \
--address $
{KUBERNETES_PUBLIC_ADDRESS} \
--ports 6443 \
--region $(gcloud config get-value compute/region) \
--targe> KUBERNETES_PUBLIC_ADDRESS=$(gcloud compute addresses describe kubernetes-the-hard-way \
> --region $(gcloud config get-value compute/region) \
> --format 'value(address)')
>
> gcloud compute http-health-checks create kubernetes \
> --description "Kubernetes Health Check" \
> --host "kubernetes.default.svc.cluster.local" \
> --request-path "/healthz"
>
> gcloud compute firewall-rules create kubernetes-the-hard-way-allow-health-check \
> --network kubernetes-the-hard-way \
> --source-ranges 209.85.152.0/22,209.85.204.0/22,35.191.0.0/16 \
> --allow tcp
>
> gcloud compute target-pools create kubernetes-target-pool \
> --http-health-check kubernetes
>
> gcloud compute target-pools add-instances kubernetes-target-pool \
> --instances controller-0,controller-1,controller-2
>
> gcloud compute forwarding-rules create kubernetes-forwarding-rule \
> --address ${KUBERNETES_PUBLIC_ADDRESS} \
> --ports 6443 \
> --region $(gcloud config get-value compute/region) \
> --target-pool kubernetes-target-pool
> }
Created [https://www.googleapis.com/compute/v1/projects/sotoiwa/global/httpHealthChecks/kubernetes].
NAME HOST PORT REQUEST_PATH
kubernetes kubernetes.default.svc.cluster.local 80 /healthz
Creating firewall...⠏Created [https://www.googleapis.com/compute/v1/projects/sotoiwa/global/firewalls/kubernetes-the-hard-way-allow-health-check].
Creating firewall...done.
NAME NETWORK DIRECTION PRIORITY ALLOW DENY DISABLED
kubernetes-the-hard-way-allow-health-check kubernetes-the-hard-way INGRESS 1000 tcp False
Created [https://www.googleapis.com/compute/v1/projects/sotoiwa/regions/asia-northeast1/targetPools/kubernetes-target-pool].
NAME REGION SESSION_AFFINITY BACKUP HEALTH_CHECKS
kubernetes-target-pool asia-northeast1 NONE kubernetes
Updated [https://www.googleapis.com/compute/v1/projects/sotoiwa/regions/asia-northeast1/targetPools/kubernetes-target-pool].
Created [https://www.googleapis.com/compute/v1/projects/sotoiwa/regions/asia-northeast1/forwardingRules/kubernetes-forwarding-rule].
sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way
$



Verification

API Server公開用の外部IPを確認する。


コマンド

KUBERNETES_PUBLIC_ADDRESS=$(gcloud compute addresses describe kubernetes-the-hard-way \

--region $(gcloud config get-value compute/region) \
--format 'value(address)')

作業用PCからHTTPリクエストを投げ、Kubernetesのバージョンが取得出来ることを確認する。


コマンド

curl --cacert ca.pem https://${KUBERNETES_PUBLIC_ADDRESS}:6443/version



実行ログ

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ curl --cacert ca.pem https://${KUBERNETES_PUBLIC_ADDRESS}:6443/version
{
"major": "1",
"minor": "12",
"gitVersion": "v1.12.0",
"gitCommit": "0ed33881dc4355495f623c6f22e7dd0b7632b7c0",
"gitTreeState": "clean",
"buildDate": "2018-09-27T16:55:41Z",
"goVersion": "go1.10.4",
"compiler": "gc",
"platform": "linux/amd64"
}sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way
$


Bootstrapping the Kubernetes Worker Nodes

https://github.com/kelseyhightower/kubernetes-the-hard-way/blob/master/docs/09-bootstrapping-kubernetes-workers.md

このLabではWorkerノードのk8sコンポーネント(kubelet、kube-proxy)を起動する。


Prerequisites

このLabの作業は各Workerノードで行う。


Running commands in parallel with tmux

(省略)


Provisioning a Kubernetes Worker Node

依存パッケージをインストールする。

{

sudo apt-get update
sudo apt-get -y install socat conntrack ipset
}


Download and Install Worker Binaries

cri-tools、runcs、runc、cni-plugins、containerdのバイナリをダウンロードする。runcsは公式バイナリではなくこのチュートリアル用のもの?それぞれのリリースページは以下。

kubectl、kube-proxy、kubeletは先ほどMasterノードのコンポーネントをダウンロードしたときと同じtarに入っている。

wget -q --show-progress --https-only --timestamping \

https://github.com/kubernetes-sigs/cri-tools/releases/download/v1.12.0/crictl-v1.12.0-linux-amd64.tar.gz \
https://storage.googleapis.com/kubernetes-the-hard-way/runsc-50c283b9f56bb7200938d9e207355f05f79f0d17 \
https://github.com/opencontainers/runc/releases/download/v1.0.0-rc5/runc.amd64 \
https://github.com/containernetworking/plugins/releases/download/v0.6.0/cni-plugins-amd64-v0.6.0.tgz \
https://github.com/containerd/containerd/releases/download/v1.2.0-rc.0/containerd-1.2.0-rc.0.linux-amd64.tar.gz \
https://storage.googleapis.com/kubernetes-release/release/v1.12.0/bin/linux/amd64/kubectl \
https://storage.googleapis.com/kubernetes-release/release/v1.12.0/bin/linux/amd64/kube-proxy \
https://storage.googleapis.com/kubernetes-release/release/v1.12.0/bin/linux/amd64/kubelet

ディレクトリーを作成する。

sudo mkdir -p \

/etc/cni/net.d \
/opt/cni/bin \
/var/lib/kubelet \
/var/lib/kube-proxy \
/var/lib/kubernetes \
/var/run/kubernetes

バイナリをインストールする。



  • kube-proxykubeletruncrunsccrictl/usr/local/bin/

  • cniプラグインは/opt/cni/bin/


  • containerd/bin/

{

sudo mv runsc-50c283b9f56bb7200938d9e207355f05f79f0d17 runsc
sudo mv runc.amd64 runc
chmod +x kubectl kube-proxy kubelet runc runsc
sudo mv kubectl kube-proxy kubelet runc runsc /usr/local/bin/
sudo tar -xvf crictl-v1.12.0-linux-amd64.tar.gz -C /usr/local/bin/
sudo tar -xvf cni-plugins-amd64-v0.6.0.tgz -C /opt/cni/bin/
sudo tar -xvf containerd-1.2.0-rc.0.linux-amd64.tar.gz -C /
}


Configure CNI Networking

この時点ではインターフェースは以下のみ。

sotoiwa@worker-0:~$ ip -d a

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 promiscuity 0 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1460 qdisc fq_codel state UP group default qlen 1000
link/ether 42:01:0a:f0:00:14 brd ff:ff:ff:ff:ff:ff promiscuity 0 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535
inet 10.240.0.20/32 scope global dynamic ens4
valid_lft 79565sec preferred_lft 79565sec
inet6 fe80::4001:aff:fef0:14/64 scope link
valid_lft forever preferred_lft forever
sotoiwa@worker-0:~$

インスタンスのメタデータからPodサブネットのCIDRを取得する。


コマンド

POD_CIDR=$(curl -s -H "Metadata-Flavor: Google" \

http://metadata.google.internal/computeMetadata/v1/instance/attributes/pod-cidr)


実行ログ

sotoiwa@worker-0:~$ POD_CIDR=$(curl -s -H "Metadata-Flavor: Google" \

> http://metadata.google.internal/computeMetadata/v1/instance/attributes/pod-cidr)
sotoiwa@worker-0:~$ echo $POD_CIDR
10.200.0.0/24
sotoiwa@worker-0:~$

ブリッジネットワークの設定ファイルを作成する。


コマンド

cat <<EOF | sudo tee /etc/cni/net.d/10-bridge.conf

{
"cniVersion": "0.3.1",
"name": "bridge",
"type": "bridge",
"bridge": "cnio0",
"isGateway": true,
"ipMasq": true,
"ipam": {
"type": "host-local",
"ranges": [
[{"subnet": "${POD_CIDR}"}]
],
"routes": [{"dst": "0.0.0.0/0"}]
}
}
EOF


実行ログ

sotoiwa@worker-0:~$ cat <<EOF | sudo tee /etc/cni/net.d/10-bridge.conf

> {
> "cniVersion": "0.3.1",
> "name": "bridge",
> "type": "bridge",
> "bridge": "cnio0",
> "isGateway": true,
> "ipMasq": true,
> "ipam": {
> "type": "host-local",
> "ranges": [
> [{"subnet": "${POD_CIDR}"}]
> ],
> "routes": [{"dst": "0.0.0.0/0"}]
> }
> }
> EOF
{
"cniVersion": "0.3.1",
"name": "bridge",
"type": "bridge",
"bridge": "cnio0",
"isGateway": true,
"ipMasq": true,
"ipam": {
"type": "host-local",
"ranges": [
[{"subnet": "10.200.0.0/24"}]
],
"routes": [{"dst": "0.0.0.0/0"}]
}
}
sotoiwa@worker-0:~$

ループバックネットワークの設定ファイルを作成する。


コマンド

cat <<EOF | sudo tee /etc/cni/net.d/99-loopback.conf

{
"cniVersion": "0.3.1",
"type": "loopback"
}
EOF


実行ログ

sotoiwa@worker-0:~$ cat <<EOF | sudo tee /etc/cni/net.d/99-loopback.conf

> {
> "cniVersion": "0.3.1",
> "type": "loopback"
> }
> EOF
{
"cniVersion": "0.3.1",
"type": "loopback"
}
sotoiwa@worker-0:~$


Configure containerd

containerdの設定をする。

(参考)

docker-containerd、docker-containerd-shim、 docker-containerd-ctr、docker-runc

gVisorを使ってdockerコンテナをより安全に利用する

ディレクトリーを作成する。

sudo mkdir -p /etc/containerd/

設定ファイルを作成する。untrustedなワークロードはgVisor(runsc)で実行する


コマンド

cat << EOF | sudo tee /etc/containerd/config.toml

[plugins]
[plugins.cri.containerd]
snapshotter = "overlayfs"
[plugins.cri.containerd.default_runtime]
runtime_type = "io.containerd.runtime.v1.linux"
runtime_engine = "/usr/local/bin/runc"
runtime_root = ""
[plugins.cri.containerd.untrusted_workload_runtime]
runtime_type = "io.containerd.runtime.v1.linux"
runtime_engine = "/usr/local/bin/runsc"
runtime_root = "/run/containerd/runsc"
[plugins.cri.containerd.gvisor]
runtime_type = "io.containerd.runtime.v1.linux"
runtime_engine = "/usr/local/bin/runsc"
runtime_root = "/run/containerd/runsc"
EOF


実行ログ

sotoiwa@worker-0:~$ cat << EOF | sudo tee /etc/containerd/config.toml

> [plugins]
> [plugins.cri.containerd]
> snapshotter = "overlayfs"
> [plugins.cri.containerd.default_runtime]
> runtime_type = "io.containerd.runtime.v1.linux"
> runtime_engine = "/usr/local/bin/runc"
> runtime_root = ""
> [plugins.cri.containerd.untrusted_workload_runtime]
> runtime_type = "io.containerd.runtime.v1.linux"
> runtime_engine = "/usr/local/bin/runsc"
> runtime_root = "/run/containerd/runsc"
> [plugins.cri.containerd.gvisor]
> runtime_type = "io.containerd.runtime.v1.linux"
> runtime_engine = "/usr/local/bin/runsc"
> runtime_root = "/run/containerd/runsc"
> EOF
[plugins]
[plugins.cri.containerd]
snapshotter = "overlayfs"
[plugins.cri.containerd.default_runtime]
runtime_type = "io.containerd.runtime.v1.linux"
runtime_engine = "/usr/local/bin/runc"
runtime_root = ""
[plugins.cri.containerd.untrusted_workload_runtime]
runtime_type = "io.containerd.runtime.v1.linux"
runtime_engine = "/usr/local/bin/runsc"
runtime_root = "/run/containerd/runsc"
[plugins.cri.containerd.gvisor]
runtime_type = "io.containerd.runtime.v1.linux"
runtime_engine = "/usr/local/bin/runsc"
runtime_root = "/run/containerd/runsc"
sotoiwa@worker-0:~$

containerd.serviceのSystemdユニットファイルを作成する。


コマンド

cat <<EOF | sudo tee /etc/systemd/system/containerd.service

[Unit]
Description=containerd container runtime
Documentation=https://containerd.io
After=network.target

[Service]
ExecStartPre=/sbin/modprobe overlay
ExecStart=/bin/containerd
Restart=always
RestartSec=5
Delegate=yes
KillMode=process
OOMScoreAdjust=-999
LimitNOFILE=1048576
LimitNPROC=infinity
LimitCORE=infinity

[Install]
WantedBy=multi-user.target
EOF



実行ログ

sotoiwa@worker-0:~$ cat <<EOF | sudo tee /etc/systemd/system/containerd.service

> [Unit]
> Description=containerd container runtime
> Documentation=https://containerd.io
> After=network.target
>
> [Service]
> ExecStartPre=/sbin/modprobe overlay
> ExecStart=/bin/containerd
> Restart=always
> RestartSec=5
> Delegate=yes
> KillMode=process
> OOMScoreAdjust=-999
> LimitNOFILE=1048576
> LimitNPROC=infinity
> LimitCORE=infinity
>
> [Install]
> WantedBy=multi-user.target
> EOF
[Unit]
Description=containerd container runtime
Documentation=https://containerd.io
After=network.target

[Service]
ExecStartPre=/sbin/modprobe overlay
ExecStart=/bin/containerd
Restart=always
RestartSec=5
Delegate=yes
KillMode=process
OOMScoreAdjust=-999
LimitNOFILE=1048576
LimitNPROC=infinity
LimitCORE=infinity

[Install]
WantedBy=multi-user.target
sotoiwa@worker-0:~$



Configure the Kubelet

Kubeletが使用する秘密鍵と証明書とkubeconfingを/var/lib/kubelet/に配置する。

{

sudo mv ${HOSTNAME}-key.pem ${HOSTNAME}.pem /var/lib/kubelet/
sudo mv ${HOSTNAME}.kubeconfig /var/lib/kubelet/kubeconfig
sudo mv ca.pem /var/lib/kubernetes/
}

Kubeletの設定フィルkubelet-config.yamlを作成する。



  • clusterDNSとして10.32.0.10を指定している


  • podCIDRを指定している

  • resolvConfはsystemd-resolved環境でのループを避けるための設定


コマンド

cat <<EOF | sudo tee /var/lib/kubelet/kubelet-config.yaml

kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
authentication:
anonymous:
enabled: false
webhook:
enabled: true
x509:
clientCAFile: "/var/lib/kubernetes/ca.pem"
authorization:
mode: Webhook
clusterDomain: "cluster.local"
clusterDNS:
- "10.32.0.10"
podCIDR: "${POD_CIDR}"
resolvConf: "/run/systemd/resolve/resolv.conf"
runtimeRequestTimeout: "15m"
tlsCertFile: "/var/lib/kubelet/${HOSTNAME}.pem"
tlsPrivateKeyFile: "/var/lib/kubelet/${HOSTNAME}-key.pem"
EOF


実行ログ

sotoiwa@worker-0:~$ cat <<EOF | sudo tee /var/lib/kubelet/kubelet-config.yaml

> kind: KubeletConfiguration
> apiVersion: kubelet.config.k8s.io/v1beta1
> authentication:
> anonymous:
> enabled: false
> webhook:
> enabled: true
> x509:
> clientCAFile: "/var/lib/kubernetes/ca.pem"
> authorization:
> mode: Webhook
> clusterDomain: "cluster.local"
> clusterDNS:
> - "10.32.0.10"
> podCIDR: "${POD_CIDR}"
> resolvConf: "/run/systemd/resolve/resolv.conf"
> runtimeRequestTimeout: "15m"
> tlsCertFile: "/var/lib/kubelet/${HOSTNAME}.pem"
> tlsPrivateKeyFile: "/var/lib/kubelet/${HOSTNAME}-key.pem"
> EOF
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
authentication:
anonymous:
enabled: false
webhook:
enabled: true
x509:
clientCAFile: "/var/lib/kubernetes/ca.pem"
authorization:
mode: Webhook
clusterDomain: "cluster.local"
clusterDNS:
- "10.32.0.10"
podCIDR: "10.200.0.0/24"
resolvConf: "/run/systemd/resolve/resolv.conf"
runtimeRequestTimeout: "15m"
tlsCertFile: "/var/lib/kubelet/worker-0.pem"
tlsPrivateKeyFile: "/var/lib/kubelet/worker-0-key.pem"
sotoiwa@worker-0:~$

kubelet.serviceのSystemdユニットファイルを作成する。

(参考)

kubelet


コマンド

cat <<EOF | sudo tee /etc/systemd/system/kubelet.service

[Unit]
Description=Kubernetes Kubelet
Documentation=https://github.com/kubernetes/kubernetes
After=containerd.service
Requires=containerd.service

[Service]
ExecStart=/usr/local/bin/kubelet \\
--config=/var/lib/kubelet/kubelet-config.yaml \\
--container-runtime=remote \\
--container-runtime-endpoint=unix:///var/run/containerd/containerd.sock \\
--image-pull-progress-deadline=2m \\
--kubeconfig=/var/lib/kubelet/kubeconfig \\
--network-plugin=cni \\
--register-node=true \\
--v=2
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF



実行ログ

sotoiwa@worker-0:~$ cat <<EOF | sudo tee /etc/systemd/system/kubelet.service

> [Unit]
> Description=Kubernetes Kubelet
> Documentation=https://github.com/kubernetes/kubernetes
> After=containerd.service
> Requires=containerd.service
>
> [Service]
> ExecStart=/usr/local/bin/kubelet \\
> --config=/var/lib/kubelet/kubelet-config.yaml \\
> --container-runtime=remote \\
> --container-runtime-endpoint=unix:///var/run/containerd/containerd.sock \\
> --image-pull-progress-deadline=2m \\
> --kubeconfig=/var/lib/kubelet/kubeconfig \\
> --network-plugin=cni \\
> --register-node=true \\
> --v=2
> Restart=on-failure
> RestartSec=5
>
> [Install]
> WantedBy=multi-user.target
> EOF
[Unit]
Description=Kubernetes Kubelet
Documentation=https://github.com/kubernetes/kubernetes
After=containerd.service
Requires=containerd.service

[Service]
ExecStart=/usr/local/bin/kubelet \
--config=/var/lib/kubelet/kubelet-config.yaml \
--container-runtime=remote \
--container-runtime-endpoint=unix:///var/run/containerd/containerd.sock \
--image-pull-progress-deadline=2m \
--kubeconfig=/var/lib/kubelet/kubeconfig \
--network-plugin=cni \
--register-node=true \
--v=2
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
sotoiwa@worker-0:~$



Configure the Kubernetes Proxy

Kube Proxyが使用するkubeconfigを配置する。

sudo mv kube-proxy.kubeconfig /var/lib/kube-proxy/kubeconfig

kube-proxy-config.yaml設定ファイルを作成する。


コマンド

cat <<EOF | sudo tee /var/lib/kube-proxy/kube-proxy-config.yaml

kind: KubeProxyConfiguration
apiVersion: kubeproxy.config.k8s.io/v1alpha1
clientConnection:
kubeconfig: "/var/lib/kube-proxy/kubeconfig"
mode: "iptables"
clusterCIDR: "10.200.0.0/16"
EOF


実行ログ

sotoiwa@worker-0:~$ cat <<EOF | sudo tee /var/lib/kube-proxy/kube-proxy-config.yaml

> kind: KubeProxyConfiguration
> apiVersion: kubeproxy.config.k8s.io/v1alpha1
> clientConnection:
> kubeconfig: "/var/lib/kube-proxy/kubeconfig"
> mode: "iptables"
> clusterCIDR: "10.200.0.0/16"
> EOF
kind: KubeProxyConfiguration
apiVersion: kubeproxy.config.k8s.io/v1alpha1
clientConnection:
kubeconfig: "/var/lib/kube-proxy/kubeconfig"
mode: "iptables"
clusterCIDR: "10.200.0.0/16"
sotoiwa@worker-0:~$

kube-proxy.serviceのSystemdユニットファイルを作成する。

(参考)

kube-proxy


コマンド

cat <<EOF | sudo tee /etc/systemd/system/kube-proxy.service

[Unit]
Description=Kubernetes Kube Proxy
Documentation=https://github.com/kubernetes/kubernetes

[Service]
ExecStart=/usr/local/bin/kube-proxy \\
--config=/var/lib/kube-proxy/kube-proxy-config.yaml
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF



実行ログ

sotoiwa@worker-0:~$ cat <<EOF | sudo tee /etc/systemd/system/kube-proxy.service

> [Unit]
> Description=Kubernetes Kube Proxy
> Documentation=https://github.com/kubernetes/kubernetes
>
> [Service]
> ExecStart=/usr/local/bin/kube-proxy \\
> --config=/var/lib/kube-proxy/kube-proxy-config.yaml
> Restart=on-failure
> RestartSec=5
>
> [Install]
> WantedBy=multi-user.target
> EOF
[Unit]
Description=Kubernetes Kube Proxy
Documentation=https://github.com/kubernetes/kubernetes

[Service]
ExecStart=/usr/local/bin/kube-proxy \
--config=/var/lib/kube-proxy/kube-proxy-config.yaml
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
sotoiwa@worker-0:~$



Start the Worker Services

サービスを起動する。

{

sudo systemctl daemon-reload
sudo systemctl enable containerd kubelet kube-proxy
sudo systemctl start containerd kubelet kube-proxy
}

サービスのステータスを確認する。

sudo systemctl status containerd kubelet kube-proxy


Verification

Masterノードでkubectlコマンドを実行する。


コマンド

gcloud compute ssh controller-0 \

--command "kubectl get nodes --kubeconfig admin.kubeconfig"


実行ログ

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ gcloud compute ssh controller-0 \
> --command "kubectl get nodes --kubeconfig admin.kubeconfig"
NAME STATUS ROLES AGE VERSION
worker-0 Ready <none> 6m29s v1.12.0
worker-1 Ready <none> 6m22s v1.12.0
worker-2 Ready <none> 6m19s v1.12.0
sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way
$


Configuring kubectl for Remote Access

https://github.com/kelseyhightower/kubernetes-the-hard-way/blob/master/docs/10-configuring-kubectl.md

このLandでは作業用PCからkubectlが実行できるようにする。


The Admin Kubernetes Configuration File

API Serverへの接続には外部公開用のIPアドレスを使用する。


コマンド

{

KUBERNETES_PUBLIC_ADDRESS=$(gcloud compute addresses describe kubernetes-the-hard-way \
--region $(gcloud config get-value compute/region) \
--format 'value(address)')

kubectl config set-cluster kubernetes-the-hard-way \
--certificate-authority=ca.pem \
--embed-certs=true \
--server=https://${KUBERNETES_PUBLIC_ADDRESS}:6443

kubectl config set-credentials admin \
--client-certificate=admin.pem \
--client-key=admin-key.pem

kubectl config set-context kubernetes-the-hard-way \
--cluster=kubernetes-the-hard-way \
--user=admin

kubectl config use-context kubernetes-the-hard-way
}



実行ログ

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ {
> KUBERNETES_PUBLIC_ADDRESS=$(gcloud compute addresses describe kubernetes-the-hard-way \
> --region $(gcloud config get-value compute/region) \
> --format 'value(address)')
>
> kubectl config set-cluster kubernetes-the-hard-way \
> --certificate-authority=ca.pem \
> --embed-certs=true \
> --server=https://${KUBERNETES_PUBLIC_ADDRESS}:6443
>
> kubectl config set-credentials admin \
> --client-certificate=admin.pem \
> --client-key=admin-key.pem
>
> kubectl config set-context kubernetes-the-hard-way \
> --cluster=kubernetes-the-hard-way \
> --user=admin
>
> kubectl config use-context kubernetes-the-hard-way
> }
Cluster "kubernetes-the-hard-way" set.
User "admin" set.
Context "kubernetes-the-hard-way" created.
Switched to context "kubernetes-the-hard-way".
sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way
$


Verification

作業用PCでkubectlコマンドが実行できることを確認する。

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ kubectl get componentstatuses
NAME STATUS MESSAGE ERROR
controller-manager Healthy ok
scheduler Healthy ok
etcd-1 Healthy {"health":"true"}
etcd-0 Healthy {"health":"true"}
etcd-2 Healthy {"health":"true"}
sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
worker-0 Ready <none> 9m11s v1.12.0
worker-1 Ready <none> 9m4s v1.12.0
worker-2 Ready <none> 9m1s v1.12.0
sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way
$


Provisioning Pod Network Routes

https://github.com/kelseyhightower/kubernetes-the-hard-way/blob/master/docs/11-pod-network-routes.md

このLabではGCPのルーティングルールを作成し、ノードをまたいだPod間の通信ができるようにする。


The Routing Table

インスタンスのIPとメタデータに保存したPodサブネットのCIDRを確認する。


コマンド

for instance in worker-0 worker-1 worker-2; do

gcloud compute instances describe ${instance} \
--format 'value[separator=" "](networkInterfaces[0].networkIP,metadata.items[0].value)'
done


実行例

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ for instance in worker-0 worker-1 worker-2; do
> gcloud compute instances describe ${instance} \
> --format 'value[separator=" "](networkInterfaces[0].networkIP,metadata.items[0].value)'
> done
10.240.0.20 10.200.0.0/24
10.240.0.21 10.200.1.0/24
10.240.0.22 10.200.2.0/24
sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way
$


Routes

ルートを定義する。各Podサブネット宛のパケットを適切なノードにルーティングする。


コマンド

for i in 0 1 2; do

gcloud compute routes create kubernetes-route-10-200-${i}-0-24 \
--network kubernetes-the-hard-way \
--next-hop-address 10.240.0.2${i} \
--destination-range 10.200.${i}.0/24
done


実行例

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ for i in 0 1 2; do
> gcloud compute routes create kubernetes-route-10-200-${i}-0-24 \
> --network kubernetes-the-hard-way \
> --next-hop-address 10.240.0.2${i} \
> --destination-range 10.200.${i}.0/24
> done
Created [https://www.googleapis.com/compute/v1/projects/sotoiwa/global/routes/kubernetes-route-10-200-0-0-24].
NAME NETWORK DEST_RANGE NEXT_HOP PRIORITY
kubernetes-route-10-200-0-0-24 kubernetes-the-hard-way 10.200.0.0/24 10.240.0.20 1000
Created [https://www.googleapis.com/compute/v1/projects/sotoiwa/global/routes/kubernetes-route-10-200-1-0-24].
NAME NETWORK DEST_RANGE NEXT_HOP PRIORITY
kubernetes-route-10-200-1-0-24 kubernetes-the-hard-way 10.200.1.0/24 10.240.0.21 1000
Created [https://www.googleapis.com/compute/v1/projects/sotoiwa/global/routes/kubernetes-route-10-200-2-0-24].
NAME NETWORK DEST_RANGE NEXT_HOP PRIORITY
kubernetes-route-10-200-2-0-24 kubernetes-the-hard-way 10.200.2.0/24 10.240.0.22 1000
sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way
$

確認する。

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ gcloud compute routes list --filter "network: kubernetes-the-hard-way"
NAME NETWORK DEST_RANGE NEXT_HOP PRIORITY
default-route-9b51bcf3343f23cb kubernetes-the-hard-way 10.240.0.0/24 kubernetes-the-hard-way 1000
default-route-cb67e0e6997aee57 kubernetes-the-hard-way 0.0.0.0/0 default-internet-gateway 1000
kubernetes-route-10-200-0-0-24 kubernetes-the-hard-way 10.200.0.0/24 10.240.0.20 1000
kubernetes-route-10-200-1-0-24 kubernetes-the-hard-way 10.200.1.0/24 10.240.0.21 1000
kubernetes-route-10-200-2-0-24 kubernetes-the-hard-way 10.200.2.0/24 10.240.0.22 1000
sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way
$


Deploying the DNS Cluster Add-on

https://github.com/kelseyhightower/kubernetes-the-hard-way/blob/master/docs/12-dns-addon.md

このLabではCoreDNSをデプロイする。


The DNS Cluster Add-on

CoreDNSをデプロイする。


コマンド

kubectl apply -f https://storage.googleapis.com/kubernetes-the-hard-way/coredns.yaml



実行ログ

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ kubectl apply -f https://storage.googleapis.com/kubernetes-the-hard-way/coredns.yaml
serviceaccount/coredns created
clusterrole.rbac.authorization.k8s.io/system:coredns created
clusterrolebinding.rbac.authorization.k8s.io/system:coredns created
configmap/coredns created
deployment.extensions/coredns created
service/kube-dns created
sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way
$

確認する。Serviceが10.32.0.10というIPであるのはマニフェストにそう書いてあるから。

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ kubectl get pods -l k8s-app=kube-dns -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-699f8ddd77-9p52h 1/1 Running 0 30s
coredns-699f8ddd77-pnqgg 1/1 Running 0 30s
sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way
$ kubectl get svc -n kube-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns ClusterIP 10.32.0.10 <none> 53/UDP,53/TCP 4d22h
sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way
$

Podが稼働したノードを確認すると、CNIプラグインによってブリッジとvethができていることが確認できる。

sotoiwa@worker-0:~$ ip -d a

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 promiscuity 0 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1460 qdisc fq_codel state UP group default qlen 1000
link/ether 42:01:0a:f0:00:14 brd ff:ff:ff:ff:ff:ff promiscuity 0 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535
inet 10.240.0.20/32 scope global dynamic ens4
valid_lft 76914sec preferred_lft 76914sec
inet6 fe80::4001:aff:fef0:14/64 scope link
valid_lft forever preferred_lft forever
3: cnio0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 0a:58:0a:c8:00:01 brd ff:ff:ff:ff:ff:ff promiscuity 0
bridge forward_delay 1500 hello_time 200 max_age 2000 ageing_time 30000 stp_state 0 priority 32768 vlan_filtering 0 vlan_protocol 802.1Q bridge_id 8000.a:58:a:c8:0:1 designated_root 8000.a:58:a:c8:0:1 root_port 0 root_path_cost 0 topology_change 0 topology_change_detected 0 hello_timer 0.00 tcn_timer 0.00 topology_change_timer 0.00 gc_timer 105.05 vlan_default_pvid 1 vlan_stats_enabled 0 group_fwd_mask 0 group_address 01:80:c2:00:00:00 mcast_snooping 1 mcast_router 1 mcast_query_use_ifaddr 0 mcast_querier 0 mcast_hash_elasticity 4 mcast_hash_max 512 mcast_last_member_count 2 mcast_startup_query_count 2 mcast_last_member_interval 100 mcast_membership_interval 26000 mcast_querier_interval 25500 mcast_query_interval 12500 mcast_query_response_interval 1000 mcast_startup_query_interval 3124 mcast_stats_enabled 0 mcast_igmp_version 2 mcast_mld_version 1 nf_call_iptables 0 nf_call_ip6tables 0 nf_call_arptables 0 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535
inet 10.200.0.1/24 scope global cnio0
valid_lft forever preferred_lft forever
inet6 fe80::649e:f8ff:fe02:8877/64 scope link
valid_lft forever preferred_lft forever
4: veth797b7424@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master cnio0 state UP group default
link/ether 7e:7d:3a:72:7e:d0 brd ff:ff:ff:ff:ff:ff link-netnsid 0 promiscuity 1
veth
bridge_slave state forwarding priority 32 cost 2 hairpin off guard off root_block off fastleave off learning on flood on port_id 0x8001 port_no 0x1 designated_port 32769 designated_cost 0 designated_bridge 8000.a:58:a:c8:0:1 designated_root 8000.a:58:a:c8:0:1 hold_timer 0.00 message_age_timer 0.00 forward_delay_timer 0.00 topology_change_ack 0 config_pending 0 proxy_arp off proxy_arp_wifi off mcast_router 1 mcast_fast_leave off mcast_flood on neigh_suppress off group_fwd_mask 0x0 group_fwd_mask_str 0x0 vlan_tunnel off numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535
inet6 fe80::7c7d:3aff:fe72:7ed0/64 scope link
valid_lft forever preferred_lft forever
sotoiwa@worker-0:~$

ノードのルーティングテーブルを表示すると以下のようになっている。10.200.0.0/24は自身のノードに割り当てているpod-cidrであり、cnio0ブリッジへルーティングしている。それ以外はPVCのデフォルトゲートウェイである10.240.0.1へルーティングしている。

sotoiwa@worker-0:~$ ip r

default via 10.240.0.1 dev ens4 proto dhcp metric 100
10.200.0.0/24 dev cnio0 proto kernel scope link src 10.200.0.1
10.240.0.1 dev ens4 proto dhcp scope link metric 100
sotoiwa@worker-0:~$


Verification

busyboxのPodを使って動作確認する。busyboxは1.28.4以下のバージョンを使わないと上手くいかないかもしれない。

(参考)

dns can't resolve kubernetes.default and/or cluster.local

Depoymentを作成してPodを起動する。


コマンド

kubectl run busybox --image=busybox:1.28 --command -- sleep 3600



実行ログ

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ kubectl run busybox --image=busybox:1.28 --command -- sleep 3600
kubectl run --generator=deployment/apps.v1beta1 is DEPRECATED and will be removed in a future version. Use kubectl create instead.
deployment.apps/busybox created
sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way
$

Pod名を変数に入れる。

POD_NAME=$(kubectl get pods -l run=busybox -o jsonpath="{.items[0].metadata.name}")

kubernetesが名前解決できるか確認する。


コマンド

kubectl exec -ti $POD_NAME -- nslookup kubernetes



実行ログ

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ kubectl exec -ti $POD_NAME -- nslookup kubernetes
Server: 10.32.0.10
Address 1: 10.32.0.10 kube-dns.kube-system.svc.cluster.local

Name: kubernetes
Address 1: 10.32.0.1 kubernetes.default.svc.cluster.local
sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way
$



Smoke Test

このLabではクラスターが機能しているかテストする。


Data Encryption

Secretを作成する。

kubectl create secret generic kubernetes-the-hard-way \

--from-literal="mykey=mydata"

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"


実行ログ

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ 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 b7 94 88 06 f0 45 07 |:v1:key1:.....E.|
00000050 90 c7 3c 77 8c ee d7 66 39 d6 12 fd 25 32 27 e6 |..<w...f9...%2'.|
00000060 2e ac 0d 8b f6 24 17 13 92 bf 79 64 41 a3 0c 71 |.....$....ydA..q|
00000070 5b 67 bc 2e d9 eb 82 aa 29 eb 45 c4 d4 e7 75 35 |[g......).E...u5|
00000080 81 4c 6e 81 b2 2f a6 be 2a 7e 56 33 fc 44 10 db |.Ln../..*~V3.D..|
00000090 b4 aa 76 f6 5d 2f 3d 57 e1 e1 39 ac eb 56 6b a6 |..v.]/=W..9..Vk.|
000000a0 89 18 1c 75 fb 5e a7 7a 1f 63 cd 21 46 5b 9d 82 |...u.^.z.c.!F[..|
000000b0 bc e4 30 36 72 6e 23 4a 68 62 f6 72 57 0e b4 e7 |..06rn#Jhb.rW...|
000000c0 13 4e 99 41 8f e3 0a 68 f8 dd c4 3a 33 1b f4 b7 |.N.A...h...:3...|
000000d0 bf d8 67 45 c0 ec 72 ac 99 72 df 7f 96 70 33 d1 |..gE..r..r...p3.|
000000e0 ee 2f 76 1a cf 00 55 28 6c 0a |./v...U(l.|
000000ea
sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way
$

k8s:enc:aescbc:v1:key1となっていることを確認する。


Deployments

Deploymentを作成する。

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ kubectl run nginx --image=nginx
kubectl run --generator=deployment/apps.v1beta1 is DEPRECATED and will be removed in a future version. Use kubectl create instead.
deployment.apps/nginx created
sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way
$

確認する。

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ kubectl get pods -l run=nginx
NAME READY STATUS RESTARTS AGE
nginx-dbddb74b8-4pnbv 1/1 Running 0 37s
sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way
$


Port Forwarding

ポートフォワーディングできることを確認する。はじめにPod名を変数に入れる。

POD_NAME=$(kubectl get pods -l run=nginx -o jsonpath="{.items[0].metadata.name}")

ポートフォワードを行う。

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ kubectl port-forward $POD_NAME 8080:80
Forwarding from 127.0.0.1:8080 -> 80
Forwarding from [::1]:8080 -> 80

別ターミナルでcurlコマンドを実行し、Podに転送されることを確認する。

sotoiwa@Soto-no-MacBook-Air:~

$ curl --head http://127.0.0.1:8080
HTTP/1.1 200 OK
Server: nginx/1.15.6
Date: Tue, 13 Nov 2018 16:13:16 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 06 Nov 2018 13:32:09 GMT
Connection: keep-alive
ETag: "5be197d9-264"
Accept-Ranges: bytes

sotoiwa@Soto-no-MacBook-Air:~
$

Ctrl+Cでポートフォワーディングを終了する。

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ kubectl port-forward $POD_NAME 8080:80
Forwarding from 127.0.0.1:8080 -> 80
Forwarding from [::1]:8080 -> 80
Handling connection for 8080
^Csotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way
$


Logs

ログが取得出来ることを確認する。

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ kubectl logs $POD_NAME
127.0.0.1 - - [13/Nov/2018:16:13:16 +0000] "HEAD / HTTP/1.1" 200 0 "-" "curl/7.54.0" "-"
sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way
$


exec

コンテナ内でコマンドが実行できることを確認する。

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ kubectl exec -ti $POD_NAME -- nginx -v
nginx version: nginx/1.15.6
sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way
$


Services

NodePort Serviceを作成する。

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ kubectl expose deployment nginx --port 80 --type NodePort
service/nginx exposed
sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way
$

アサインされたNodePort Serviceのポート番号を変数に入れる。

NODE_PORT=$(kubectl get svc nginx \

--output=jsonpath='{range .spec.ports[0]}{.nodePort}')

worker-0の外部IPを変数に入れる。

EXTERNAL_IP=$(gcloud compute instances describe worker-0 \

--format 'value(networkInterfaces[0].accessConfigs[0].natIP)')

NodePortへのアクセスを許可するFirewall Ruleを追加する。


コマンド

gcloud compute firewall-rules create kubernetes-the-hard-way-allow-nginx-service \

--allow=tcp:${NODE_PORT} \
--network kubernetes-the-hard-way


実行ログ

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ gcloud compute firewall-rules create kubernetes-the-hard-way-allow-nginx-service \
> --allow=tcp:${NODE_PORT} \
> --network kubernetes-the-hard-way
Creating firewall...⠏Created [https://www.googleapis.com/compute/v1/projects/sotoiwa/global/firewalls/kubernetes-the-hard-way-allow-nginx-service].
Creating firewall...done.
NAME NETWORK DIRECTION PRIORITY ALLOW DENY DISABLED
kubernetes-the-hard-way-allow-nginx-service kubernetes-the-hard-way INGRESS 1000 tcp:31010 False
sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way
$

curlコマンドでアクセスできることを確認する。

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ curl -I http://${EXTERNAL_IP}:${NODE_PORT}
HTTP/1.1 200 OK
Server: nginx/1.15.6
Date: Tue, 13 Nov 2018 16:44:51 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 06 Nov 2018 13:32:09 GMT
Connection: keep-alive
ETag: "5be197d9-264"
Accept-Ranges: bytes

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way
$


Untrusted Workloads

UntrustedなPodをデプロイする。


コマンド

cat <<EOF | kubectl apply -f -

apiVersion: v1
kind: Pod
metadata:
name: untrusted
annotations:
io.kubernetes.cri.untrusted-workload: "true"
spec:
containers:
- name: webserver
image: gcr.io/hightowerlabs/helloworld:2.0.0
EOF


実行ログ

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ cat <<EOF | kubectl apply -f -
> apiVersion: v1
> kind: Pod
> metadata:
> name: untrusted
> annotations:
> io.kubernetes.cri.untrusted-workload: "true"
> spec:
> containers:
> - name: webserver
> image: gcr.io/hightowerlabs/helloworld:2.0.0
> EOF
pod/untrusted created
sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way
$


Verification

Podを確認する。

sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way

$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE
busybox-bd8fb7cbd-6t52r 1/1 Running 0 55m 10.200.1.2 worker-1 <none>
nginx-dbddb74b8-4pnbv 1/1 Running 0 40m 10.200.1.3 worker-1 <none>
untrusted 1/1 Running 0 2m13s 10.200.0.4 worker-0 <none>
sotoiwa@Soto-no-MacBook-Air:~/workspace/kubernetes-the-hard-way
$

Podが稼働しているノード名を変数に入れる。

INSTANCE_NAME=$(kubectl get pod untrusted --output=jsonpath='{.spec.nodeName}')

Podが稼働しているノードにSSHログインする。

gcloud compute ssh ${INSTANCE_NAME}

gVisorの配下で稼働しているコンテナをリストする。


コマンド

sudo runsc --root /run/containerd/runsc/k8s.io list



実行ログ

sotoiwa@worker-0:~$ sudo runsc --root /run/containerd/runsc/k8s.io list

I1113 16:52:58.756368 15780 x:0] ***************************
I1113 16:52:58.756586 15780 x:0] Args: [runsc --root /run/containerd/runsc/k8s.io list]
I1113 16:52:58.756667 15780 x:0] Git Revision: 50c283b9f56bb7200938d9e207355f05f79f0d17
I1113 16:52:58.756751 15780 x:0] PID: 15780
I1113 16:52:58.756821 15780 x:0] UID: 0, GID: 0
I1113 16:52:58.756890 15780 x:0] Configuration:
I1113 16:52:58.756947 15780 x:0] RootDir: /run/containerd/runsc/k8s.io
I1113 16:52:58.757071 15780 x:0] Platform: ptrace
I1113 16:52:58.757210 15780 x:0] FileAccess: exclusive, overlay: false
I1113 16:52:58.757337 15780 x:0] Network: sandbox, logging: false
I1113 16:52:58.757494 15780 x:0] Strace: false, max size: 1024, syscalls: []
I1113 16:52:58.757617 15780 x:0] ***************************
ID PID STATUS BUNDLE CREATED OWNER
a835bf9486cc50f733ad547709d7da081d3188d5604ef92aba328cad748a29f5 15140 running /run/containerd/io.containerd.runtime.v1.linux/k8s.io/a835bf9486cc50f733ad547709d7da081d3188d5604ef92aba328cad748a29f5 0001-01-01T00:00:00Z
eb020a9beed26c2541f07af8bb35889297aceb4d44fe5b4903de7e63627fd0b2 15060 running /run/containerd/io.containerd.runtime.v1.linux/k8s.io/eb020a9beed26c2541f07af8bb35889297aceb4d44fe5b4903de7e63627fd0b2 0001-01-01T00:00:00Z
I1113 16:52:58.761825 15780 x:0] Exiting with status: 0
sotoiwa@worker-0:~$

untrusted PodのIPを取得する。

POD_ID=$(sudo crictl -r unix:///var/run/containerd/containerd.sock \

pods --name untrusted -q)

untrusted Podの中で稼働しているwebserverコンテナのIDを取得する。

CONTAINER_ID=$(sudo crictl -r unix:///var/run/containerd/containerd.sock \

ps -p ${POD_ID} -q)

webserverコンテナの中で稼働しているプロセスを表示する。


コマンド

sudo runsc --root /run/containerd/runsc/k8s.io ps ${CONTAINER_ID}



実行ログ

sotoiwa@worker-0:~$ sudo runsc --root /run/containerd/runsc/k8s.io ps ${CONTAINER_ID}

I1113 16:54:30.817005 15909 x:0] ***************************
I1113 16:54:30.817191 15909 x:0] Args: [runsc --root /run/containerd/runsc/k8s.io ps a835bf9486cc50f733ad547709d7da081d3188d5604ef92aba328cad748a29f5]
I1113 16:54:30.817265 15909 x:0] Git Revision: 50c283b9f56bb7200938d9e207355f05f79f0d17
I1113 16:54:30.817344 15909 x:0] PID: 15909
I1113 16:54:30.817410 15909 x:0] UID: 0, GID: 0
I1113 16:54:30.817475 15909 x:0] Configuration:
I1113 16:54:30.817528 15909 x:0] RootDir: /run/containerd/runsc/k8s.io
I1113 16:54:30.817651 15909 x:0] Platform: ptrace
I1113 16:54:30.817837 15909 x:0] FileAccess: exclusive, overlay: false
I1113 16:54:30.817960 15909 x:0] Network: sandbox, logging: false
I1113 16:54:30.818085 15909 x:0] Strace: false, max size: 1024, syscalls: []
I1113 16:54:30.818351 15909 x:0] ***************************
UID PID PPID C STIME TIME CMD
0 1 0 0 16:49 0s app
I1113 16:54:30.820659 15909 x:0] Exiting with status: 0
sotoiwa@worker-0:~$


Cleaning Up

https://github.com/kelseyhightower/kubernetes-the-hard-way/blob/master/docs/14-cleanup.md

このLabでは作成したGCP上のリソースを削除する。


Compute Instances

インスタンスを削除する。

gcloud -q compute instances delete \

controller-0 controller-1 controller-2 \
worker-0 worker-1 worker-2


Networking

外部ロードバランサーを削除する。

{

gcloud -q compute forwarding-rules delete kubernetes-forwarding-rule \
--region $(gcloud config get-value compute/region)

gcloud -q compute target-pools delete kubernetes-target-pool

gcloud -q compute http-health-checks delete kubernetes

gcloud -q compute addresses delete kubernetes-the-hard-way
}

Filewall Ruleを削除する。

gcloud -q compute firewall-rules delete \

kubernetes-the-hard-way-allow-nginx-service \
kubernetes-the-hard-way-allow-internal \
kubernetes-the-hard-way-allow-external \
kubernetes-the-hard-way-allow-health-check

VPCネットワークを削除する。

{

gcloud -q compute routes delete \
kubernetes-route-10-200-0-0-24 \
kubernetes-route-10-200-1-0-24 \
kubernetes-route-10-200-2-0-24

gcloud -q compute networks subnets delete kubernetes

gcloud -q compute networks delete kubernetes-the-hard-way
}