QEMU/KVM上で https://github.com/kelseyhightower/kubernetes-the-hard-wayを試してみたので、ログを残しておく。 元々の文章では、GCPを前提としているが、今回は手元のQEMU/KVM上で構築した。
バージョン一覧
- kubernetes-the-hard-way bf2850974e19c118d04fdc0809ce2ae8a0026a27
- 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
1. 事前準備
VMイメージを取得して、起動するまで。
# VMイメージの準備
$ http_dir=http://ftp.jaist.ac.jp/pub/Linux/Fedora/releases/30/Cloud/x86_64/images
$ wget $http_dir/Fedora-Cloud-Base-30-1.2.x86_64.qcow2
$ virt-customize -a /var/lib/libvirt/images/Fedora-Cloud-Base-30-1.2.x86_64.qcow2 \
--run-command 'yum remove cloud-init* -y' \
--root-password password:root
$ cd /var/lib/libvirt/images/
$ for i in 0 1 2 ; do \
sudo cp ./Fedora-Cloud-Base-30-1.2.x86_64.qcow2 controller-$i.qcow2; \
sudo cp ./Fedora-Cloud-Base-30-1.2.x86_64.qcow2 worker-$i.qcow2; \
done
# VM起動
$ for name in controller-0 controller-1 controller-2 worker-0 worker-1 worker-2
do
sudo virt-install --name=$name --virt-type kvm --graphics none \
--disk /var/lib/libvirt/images/$name.qcow2 --vcpus=1 \
--ram=512 --network network=default,model=virtio \
--import --noautoconsole
done
$ sudo virsh list --all
Id Name State
--------------------------date: 2020-07-28T00:00:00-00:00
draft: false
---
4 controller-0 実行中
5 controller-2 実行中
6 controller-1 実行中
7 worker-0 実行中
8 worker-1 実行中
9 worker-2 実行中
# VM初期設定(VMごとに)
$ hostnamectl set-hostname controller-0
$ nmcli c m "System eth0" ipv4.addresses "192.168.122.10/24" \
ipv4.method manual \
connection.autoconnect yes \
ipv4.gateway 192.168.122.1 \
ipv4.dns 8.8.8.8
$ systemctl restart NetworkManager
# host側のNW設定
$ sudo sysctl -p /etc/sysctl.conf
net.ipv4.ip_forward = 1
$ cat /etc/hosts | grep 192.168.122
192.168.122.10 controller-0
192.168.122.11 controller-1
192.168.122.12 controller-2
192.168.122.13 worker-0
192.168.122.14 worker-1
192.168.122.15 worker-2
2. クライアントツールのインストール
# Public Key Infrastructure (PKI)のため
$ wget -q --show-progress --https-only --timestamping \
https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 \
https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
$ chmod +x cfssl_linux-amd64 cfssljson_linux-amd64
$ mv cfssl_linux-amd64 /usr/local/bin/cfssl
$ mv cfssljson_linux-amd64 /usr/local/bin/cfssljson
$ cfssl version
Version: 1.2.0
Revision: dev
Runtime: go1.6
# kubectlのインストール
$ wget https://storage.googleapis.com/kubernetes-release/release/v1.12.0/bin/linux/amd64/kubectl
$ chmod +x kubectl
$ mv kubectl /usr/local/bin
$ kubectl version --client
Client Version: version.Info{Major:"1", Minor:"12", GitVersion:"v1.12.0",
GitCommit:"0ed33881dc4355495f623c6f22e7dd0b7632b7c0",
GitTreeState:"clean",
BuildDate:"2018-09-27T17:05:32Z",
GoVersion:"go1.10.4", Compiler:"gc",
Platform:"linux/amd64"}
3. コンピュートリソースの準備
今回はGCPを使わないので省略。
4. 認証局のセットアップとTLS証明書の生成
CloudFlareのPKIツールキットを使って、PKI基盤を作る。 まず、CA(Certificate Authority)のための設定ファイル、証明書、秘密鍵を作る。
$ cat > ca-config.json <<EOF
{
"signing": {
"default": {
"expiry": "8760h"
},
"profiles": {
"kubernetes": {
"usages": ["signing", "key encipherment", "server auth", "client auth"],
"expiry": "8760h"
}
}
}
}
EOF
$ cat > ca-csr.json <<EOF
{
"CN": "Kubernetes",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "US",
"L": "Portland",
"O": "Kubernetes",
"OU": "CA",
"ST": "Oregon"
}
]
}
EOF
$ cfssl gencert -initca ca-csr.json | cfssljson -bare ca
[INFO] generating a new CA key and certificate from CSR
[INFO] generate received request
[INFO] received CSR
[INFO] generating key: rsa-2048
[INFO] encoded CSR
[INFO] signed certificate with serial number XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
$ ls ca*pem
ca-key.pem ca.pem
続いて、各コンポーネントのクライアント・サーバ証明書を作る。 また、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
[INFO] generate received request
[INFO] received CSR
[INFO] generating key: rsa-2048
[INFO] encoded CSR
[INFO] signed certificate with serial number XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
$ ls admin*pem
admin-key.pem admin.pem
Node AuthorizerがKubeletを認証する。証明書と秘密鍵をノードごとに作成する。
$ 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
ip=`cat /etc/hosts | grep $instance | awk '{print $1;}'`
echo $instance $ip
cfssl gencert \
-ca=ca.pem \
-ca-key=ca-key.pem \
-config=ca-config.json \
-hostname=${instance},${ip} \
-profile=kubernetes \
${instance}-csr.json | cfssljson -bare ${instance}
done
$ ls worker*pem
worker-0-key.pem worker-0.pem worker-1-key.pem worker-1.pem worker-2-key.pem worker-2.pem
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
[INFO] generate received request
[INFO] received CSR
[INFO] generating key: rsa-2048
[INFO] encoded CSR
[INFO] signed certificate with serial number XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
$ ls kube-controller-manager*pem
kube-controller-manager-key.pem kube-controller-manager.pem
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
[INFO] generate received request
[INFO] received CSR
[INFO] generating key: rsa-2048
[INFO] encoded CSR
[INFO] signed certificate with serial number XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
$ ls kube-proxy*pem
kube-proxy-key.pem kube-proxy.pem
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
[INFO] generate received request
[INFO] received CSR
[INFO] generating key: rsa-2048
[INFO] encoded CSR
[INFO] signed certificate with serial number XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
$ ls kube-scheduler*pem
kube-scheduler-key.pem kube-scheduler.pem
kubernetes APIサーバのクライアント証明書と秘密鍵を作成する。 LBをたてるのはめんどうなので、controller-0をAPI public addressとした。
$ KUBERNETES_PUBLIC_ADDRESS=192.168.122.10
$ 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
[INFO] generate received request
[INFO] received CSR
[INFO] generating key: rsa-2048
[INFO] encoded CSR
[INFO] signed certificate with serial number XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
$ ls kubernetes*pem
kubernetes-key.pem kubernetes.pem
service-accountの証明書と秘密鍵を作る。
$ 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
[INFO] generate received request
[INFO] received CSR
[INFO] generating key: rsa-2048
[INFO] encoded CSR
[INFO] signed certificate with serial number XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
$ ls service-account*pem
service-account-key.pem service-account.pem
サーバ・クライアント証明書を配布する。
$ for instance in worker-0 worker-1 worker-2; do
scp ca.pem ${instance}-key.pem ${instance}.pem root@${instance}:~/
done
$ for instance in controller-0 controller-1 controller-2; do
scp ca.pem ca-key.pem kubernetes-key.pem kubernetes.pem \
service-account-key.pem service-account.pem root@${instance}:~/
done
続きは余裕があるときにやっていく。