ぷりぷりあぷりけーしょんずインフラ担当による ぷりぷりあぷりけーしょんず Advent Calendar 2019 の3日目
1.目標
これを作ります。
2.環境
ホストOS
- メモリ:16G
- OS:Ubuntu18.04.2
- KVM:
$ virsh version
Compiled against library: libvirt 4.0.0
Using library: libvirt 4.0.0
Using API: QEMU 4.0.0
Running hypervisor: QEMU 2.11.1
ゲストOS(Master,Worker01,Worker02)
- メモリ:4G
- OS:Ubuntu18.04.2
- Kubernetes:1.15.3
3.仮想マシンの作成
3.1.必要パッケージのインストール
$ sudo apt install qemu-kvm libvirt-bin virtinst bridge-utils libosinfo-bin libguestfs-tools virt-top
3.2.仮想マシンの作成
3.2.1.インスタンスイメージの作成
sudo virt-install \
--name master \
--ram 4096 \
--vcpus 2 \
--disk path=/var/lib/libvirt/images/master.img,size=20,format=qcow2 \
--os-type linux \
--os-variant ubuntu18.04 \
--network bridge=virbr0 \
--graphics none \
--console pty,target_type=serial \
--location 'http://jp.archive.ubuntu.com/ubuntu/dists/bionic/main/installer-amd64/' \
--extra-args 'console=ttyS0,115200n8 serial'
3.2.2.仮想マシンのコンソールへアクセスする設定
最終的には仮想マシンへSSHで接続しますが、SSHやNWの基本設定の操作をするために下記の手順を踏みます。
$ sudo virsh shutdown master
$ sudo guestmount -d master -i /mnt
$ sudo ln -s /mnt/lib/systemd/getty@.service /mnt/etc/systemd/system/getty.target.wants/getty@ttyS0.service
$ sudo umount /mnt
3.2.3.仮想マシンの諸設定
-
仮想マシンのIPアドレスを手動で設定します
ホストOSで以下を実行
$ sudo virsh start master --console
ゲストOSへログイン後以下を実行
$ sudo su -
# vi /etc/netplan/01-netcfg.yaml
# This file describes the network interfaces available on your system # For more information, see netplan(5). network: version: 2 renderer: networkd ethernets: ens2: dhcp4: false addresses: - 192.168.122.2/24 gateway4: 192.168.122.1 nameservers: addresses: - 192.168.122.1
# netplan apply
-
Kubernetesを利用可能にする
# swapoff -a
# vi /etc/fstab
## 以下の行をコメントアウト /swapfile none swap sw 0 0
# vi /etc/hosts
# 作成した仮想マシンの情報を追記 # IPアドレスは各自読み替えてください 192.168.122.2 master 192.168.122.3 node01 192.168.122.4 node02
# echo net.bridge.bridge-nf-call-iptables = 1 >> /etc/sysctl.conf
# echo net.bridge.bridge-nf-call-ip6tables = 1 >> /etc/sysctl.conf
# echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
またこの際にホストOSから仮想マシンへSSHするユーザを作成したり、SSHのための公開鍵のコピーを行なってください。
3.2.4.仮想マシンへDocker,Kubernetesのインストール
上記に引き続き仮想マシンへログインした状態で作業してください。
公式サイトにある手順を実施していますが、バージョンを明示するため冗長ですが手順を示します。
-
Docker
# apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common
# curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
# apt-key fingerprint 0EBFCD88
# add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
# apt-get update
# apt-get install docker-ce=5:18.09.9~3-0~ubuntu-bionic docker-ce-cli=5:18.09.9~3-0~ubuntu-bionic containerd.io
-
Kubernetes
# apt-get update && sudo apt-get install -y apt-transport-https curl
# curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
# echo "deb https://apt.kubernetes.io/ kubernetes-xenial main" | tee /etc/apt/sources.list.d/kubernetes.list
# apt-get update
# apt-get install -y kubelet kubeadm kubectl
# apt-mark hold kubelet kubeadm kubectl
3.3.仮想マシンを複製
ここまでの手順で作成したMaster用仮想マシンを雛形として、Worker用の仮想マシンを作成します。
$ sudo virsh shutdown master
$ sudo virt-clone --original master --name node01 --file /var/lib/libvirt/images/node01.img
これでWorker用仮想マシンが作成されたので3.2.3.のIPアドレスの手動設定
だけして、仮想マシンの作成は終了です。
4.Kubernetesクラスタ作成
Masterノード
Master用仮想マシンへログインし、以下のコマンドを実行します。
--pod-network-cidr
オプションはPodの所属するネットワークの指定に利用します。Calicoのデフォルトが192.168.0.0/16
でKVMのネットワークとバッティングするため10.x.x.x/16
で設定すると良いでしょう。
$ sudo kubeadm init --apiserver-advertise-address=192.168.122.2 --pod-network-cidr=10.64.0.0/16
(前略)
To start using your cluster, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join 192.168.122.2:6443 --token 0bno9n.2h84n6b0nhl71iyy \
--discovery-token-ca-cert-hash sha256:5fc061867c95d29841675ec575af7787a84316167a5b92e73b7f7a483579c100
コマンドの結果にある、mkdir~chown
までのコマンドを実行することでkubectl
によるKubernetesの操作が可能になります。
Workerノード
Masterノードで実行したコマンドの結果の最終行にあるコマンドを各Workerノードで実行します。
$ sudo kubeadm join 192.168.122.2:6443 --token 0bno9n.2h84n6b0nhl71iyy --discovery-token-ca-cert-hash sha256:5fc061867c95d29841675ec575af7787a84316167a5b92e73b7f7a483579c100
クラスタの確認
Masterノードで下記のコマンドを実行してNodeの状態を確認します。
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
master NotReady master 101s v1.15.3
node01 NotReady <none> 21s v1.15.3
node02 NotReady <none> 5s v1.15.3
CNIを導入していないのでNodeのStatusがNotReady
ですが、kubectlでNodeの情報を取得できていることがわかります。
5.Calicoのインストール
Calicoとは
DockerでデプロイしたコンテナはそのDockerのあるホスト上でのみ通信可能です。(緑矢印)
複数のホスト上でDockerを構築した場合、コンテナが外方向で通信可能な範囲は他のホストのインターフェイスまでになります。(青矢印)
ネットワークの異なる他のホストのコンテナへはアクセスできません。(紫矢印)
Calicoを利用することで、Kubernetesクラスタ作成時に指定したpod-network-cidrのネットワーク内でコンテナ(Pod)間の通信が可能になります。
コンテナのIPアドレスの共有はetcdとBGPを利用します。
etcdのインストール
Calicoの設定情報やIPや各コンテナのIPを保存するためのetcdPodをデプロイします。
$ wget https://docs.projectcalico.org/v3.5/getting-started/kubernetes/installation/hosted/etcd.yaml
$ kubectl apply -f etcd.yaml
Calicoのインストール
$ wget https://docs.projectcalico.org/v3.5/getting-started/kubernetes/installation/hosted/calico.yaml
$ vi calico.yaml
IPIPモードをOFFに、Calicoの利用するネットワークの設定にpod-network-cidrで指定した値を書き込みます。
217 - name: CALICO_IPV4POOL_IPIP
218 value: "off"
225 # The default IPv4 pool to create on startup if none exists. Pod IPs will be
226 # chosen from this range. Changing this value after installation will have
227 # no effect. This should fall within `--cluster-cidr`.
228 - name: CALICO_IPV4POOL_CIDR
229 value: "10.64.0.0/16"
$ kubectl apply -f calico.yaml
configmap/calico-config created
secret/calico-etcd-secrets created
daemonset.extensions/calico-node created
serviceaccount/calico-node created
deployment.extensions/calico-kube-controllers created
serviceaccount/calico-kube-controllers created
clusterrole.rbac.authorization.k8s.io/calico-kube-controllers created
clusterrolebinding.rbac.authorization.k8s.io/calico-kube-controllers created
clusterrole.rbac.authorization.k8s.io/calico-node created
clusterrolebinding.rbac.authorization.k8s.io/calico-node created
$ kubectl get pods -A
Calicoのコンポーネントがデプロイされていることがわかります。
またCalicoをデプロイするまではステータスがPendingであった、coredns
PodもRunningになっています。
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system calico-etcd-4m6k2 1/1 Running 0 73s
kube-system calico-kube-controllers-5d57bd4b96-4bj8s 1/1 Running 1 100s
kube-system calico-node-jmsmd 1/1 Running 2 100s
kube-system calico-node-mhlnk 1/1 Running 1 100s
kube-system calico-node-v9ll2 1/1 Running 1 100s
kube-system coredns-5c98db65d4-j2h6b 1/1 Running 0 39m
kube-system coredns-5c98db65d4-x2shs 1/1 Running 0 39m
kube-system etcd-master 1/1 Running 0 38m
kube-system kube-apiserver-master 1/1 Running 0 38m
kube-system kube-controller-manager-master 1/1 Running 0 38m
kube-system kube-proxy-2xggm 1/1 Running 0 38m
kube-system kube-proxy-j9j9m 1/1 Running 0 38m
kube-system kube-proxy-p6xnw 1/1 Running 0 39m
kube-system kube-scheduler-master 1/1 Running 0 38m
6.Pod間通信の確認
冒頭にある通り、NginxPodを利用してPod間通信の確認をしていきます。
Nginxのデプロイ
$ kubectl run my-nginx --image=nginx --replicas=2 --port=80
kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.
deployment.apps/my-nginx created
$ kubectl get pods -o wide
Worker01,Worker02のそれぞれにNginxがデプロイされています。
Podの持つIPアドレスがCalicoで指定したネットワークになっていることも確認できます。
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
my-nginx-756fb87568-f9bvd 1/1 Running 0 17h 10.64.196.130 node01 <none> <none>
my-nginx-756fb87568-gpg99 1/1 Running 0 17h 10.64.140.64 node02 <none> <none>
疎通確認
-
curl用Podのデプロイ
$ kubectl run curl --image=radial/busyboxplus:curl -i --tty --rm
別ターミナルでMasterノードへログイン後
$ kubectl get pods
を実行するとcurl用Podがデプロイされたことがわかります。今回はWorker02にデプロイされました。
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES curl-6bf6db5c4f-vfwfd 1/1 Running 0 47s 10.64.140.65 node02 <none> <none> my-nginx-756fb87568-f9bvd 1/1 Running 0 17h 10.64.196.130 node01 <none> <none> my-nginx-756fb87568-gpg99 1/1 Running 0 17h 10.64.140.64 node02 <none> <none>
-
疎通確認
[ root@curl-6bf6db5c4f-vfwfd:/ ]$ curl -I 10.64.196.130
HTTP/1.1 200 OK Server: nginx/1.17.6 Date: Sun, 24 Nov 2019 07:38:15 GMT Content-Type: text/html Content-Length: 612 Last-Modified: Tue, 19 Nov 2019 12:50:08 GMT Connection: keep-alive ETag: "5dd3e500-264" Accept-Ranges: bytes
[ root@curl-6bf6db5c4f-vfwfd:/ ]$ curl -I 10.64.140.64
HTTP/1.1 200 OK Server: nginx/1.17.6 Date: Sun, 24 Nov 2019 07:42:30 GMT Content-Type: text/html Content-Length: 612 Last-Modified: Tue, 19 Nov 2019 12:50:08 GMT Connection: keep-alive ETag: "5dd3e500-264" Accept-Ranges: bytes
同一ホスト(Worker02)のPodはもちろん、異なるホスト(Worker01)への疎通についても確認できました。
Calicoの確認
Calicoの説明箇所でetcd
とBGP
を利用していると書きましたが、それの確認をしてみます。
etcdctlのインストール
-
calico-etcdのバージョン確認
$ curl http://10.96.232.136:6666/version | jq .
% Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 44 100 44 0 0 11000 0 --:--:-- --:--:-- --:--:-- 14666 { "etcdserver": "3.3.9", "etcdcluster": "3.3.0" }
-
etcdctlのインストール
$ ETCD_VER=v3.3.9
$ GOOGLE_URL=https://storage.googleapis.com/etcd
$ DOWNLOAD_URL=${GOOGLE_URL}
$ curl -L ${DOWNLOAD_URL}/${ETCD_VER}/etcd-${ETCD_VER}-linux-amd64.tar.gz -o etcd-${ETCD_VER}-linux-amd64.tar.gz
$ tar zxvf etcd-v3.3.9-linux-amd64.tar.gz
$ sudo mv etcd-v3.3.9-linux-amd64/etcdctl /usr/local/bin/
-
etcdctlのセットアップ
calico-etcdがVersion3を利用しているため、etcdctlでもVersion3を利用するように設定します。
--endpointsオプションには先ほどデプロイしたetcd.yamlにある
ClusterIP
を指定します。$ alias etcd='ETCDCTL_API=3 etcdctl --endpoints=10.96.232.136:6666'
$ etcd version
etcdctl version: 3.3.9 API version: 3.3
calico-etcdの確認
下記のコマンドでetcdに格納されているキーの一覧を取得可能です。
$ etcd get / --prefix --keys-only
先ほどデプロイしたNginxPodの情報についても格納されていることがわかります(JSONは整形してあります)。
$ etcd get /calico/resources/v3/projectcalico.org/workloadendpoints/default/node01-k8s-my--nginx--756fb87568--f9bvd-eth0
{
"kind": "WorkloadEndpoint",
"apiVersion": "projectcalico.org/v3",
"metadata": {
"name": "node01-k8s-my--nginx--756fb87568--f9bvd-eth0",
"generateName": "my-nginx-756fb87568-",
"namespace": "default",
"uid": "e2b350ab-0df7-11ea-a8fd-525400f19390",
"creationTimestamp": "2019-11-23T13:48:09Z",
"labels": {
"pod-template-hash": "756fb87568",
"projectcalico.org/namespace": "default",
"projectcalico.org/orchestrator": "k8s",
"projectcalico.org/serviceaccount": "default",
"run": "my-nginx"
}
},
"spec": {
"orchestrator": "k8s",
"node": "node01",
"containerID": "0baf28fb5c448b6850091691ad79c713f665e4915862c4d7713304414f02c210",
"pod": "my-nginx-756fb87568-f9bvd",
"endpoint": "eth0",
"ipNetworks": [
"10.64.196.130/32"
],
"profiles": [
"kns.default",
"ksa.default.default"
],
"interfaceName": "cali4ecc9d1d445",
"mac": "ae:61:8a:0a:7b:4d"
}
}
Calicoについてはまだまだ理解が浅いので断言はできませんが、これらの情報を利用してPod間の通信を可能にしているものと思われます。(たぶんね)
7.まとめ
ここまでで構築した環境があれば、Kubernetes上に適当なアプリケーションをデプロイするもサービスメッシュを実現するも、なんでも可能になります!
さらにこの記事で構築した環境については12/11or19
のIstio構築に続きます!
参考URL