Calico the hard wayの作業ログ

2019-11-12に作成

KubernetesのCNIプラグインにCalicoというものがあって、いま自分が運用に関わっているシステムはそれを使っているんだけど、今までちゃんとCalicoについて勉強したことがなかったので、ちょっとチュートリアルをやってみようと思う。今回はCalico the hard wayというやつ。
これはCalicoのチュートリアルではあるんだけど、いわゆるハローワールドみたいなものとは違って、Calicoの機能やCalicoを支えるコンポーネントも網羅してハンズオンするみたいな感じ。というわけで、Calicoについて勉強するには適切な題材となっている。
ただ、hard wayとあるように、ややボリュームが多いので、数日にわたって行うことになる。というわけで、せっかくだし、Crieitのボード機能を使って作業ログを残してみようと思う。

所有者限定モードのためこのボードには投稿できません ボードとは?

Days2: The Calico datastore

今日はThe Calico datastoreから。前回はKubernetesのクラスタを作った。

これからCalicoをインストールする作業を進めていくわけだけど、そのためにはCalicoが保持するデータの場所を設定する必要がある。設定場所の選択肢はKubernetesとetcdの2つ。どちらにも長所と短所がある。ざっくり言うとこんな感じ。

  • Kubernetesをデータストアとして使う: すでにあるKubernetesクラスタを利用するので、追加でなにかを用意する必要がない。また、Kubernetesがもっている様々な機構を利用することが出来る。
  • etcdををデータストアとして使う: Kubernetesに依存しない環境(例えばOpenStackなど)でCalicoを利用することができる。また、Kubernetesを意識する必要がないので、独自にスケールさせることが出来る。

Calico the hard wayではKubernetesをデータストアとして利用する。で、じゃあKubernetesをデータストアとして利用するならどうなるかというと、KubernetesのCustom resourceとしてCalicoのリソースが管理される。全部がCustome resourceというわけではない。例えば、workload endpointsなんかはPodとして管理される。兎にも角にも、Custome resourceとして管理するためにはリソース定義が必要。ということで、以下の手順でリソース定義を適用する。

$ wget 'https://docs.projectcalico.org/v3.10/manifests/crds.yaml'
...
2019-11-14 01:01:21 (3.92 MB/s) - ‘crds.yaml’ saved [4077/4077]

$ kubectl apply -f ./crds.yaml
customresourcedefinition.apiextensions.k8s.io/felixconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamblocks.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/blockaffinities.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamhandles.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamconfigs.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/bgppeers.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/bgpconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ippools.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/hostendpoints.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/clusterinformations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/globalnetworkpolicies.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/globalnetworksets.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/networkpolicies.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/networksets.crd.projectcalico.org created

次にCalicoの操作を用意にするためにcalicoctlをインストールする。

$ wget https://github.com/projectcalico/calicoctl/releases/download/v3.8.0/calicoctl
$ sudo mv calicoctl /usr/local/bin/
$ chmod +x calicoctl
$ echo 'export KUBECONFIG=${HOME}/.kube/config' >> ~/.bashrc
$ echo 'export DATASTORE_TYPE=kubernetes' >> ~/.bashrc

軽く動作確認をする。

$ calicoctl get nodes
NAME
calicothehardway-001
calicothehardway-002
calicothehardway-003
calicothehardway-004
calicothehardway-005

# ↑と同じような出力になっているかを確認 -> OK
$ kubectl get nodes
NAME                   STATUS     ROLES    AGE   VERSION
calicothehardway-001   NotReady   master   24h   v1.16.2
calicothehardway-002   NotReady   <none>   24h   v1.16.2
calicothehardway-003   NotReady   <none>   23h   v1.16.2
calicothehardway-004   NotReady   <none>   23h   v1.16.2
calicothehardway-005   NotReady   <none>   23h   v1.16.2

# これはからの出力になるのが期待通り。
$ calicoctl get ippools
NAME   CIDR   SELECTOR

今日はここまで。

Day1: Standing up Kubernetes

初日はStanding up Kubernetesから。

マシンが5台必要らしいので、パパっと用意する。ドキュメントではUbuntu 18.04 LTSが指定されているが、諸事情により、CentOS7.7を使う。

まず必要なソフトウェアとして、dockerとkubeadmをインストールする必要がある。手順は以下のリンクを参照すれば良い。

各ホストへのインストールが終わったら、適用な1台でKubernetesの初期設定を行う。

$ sudo kubeadm init --pod-network-cidr=192.168.0.0/16
[init] Using Kubernetes version: v1.16.2
[preflight] Running pre-flight checks
error execution phase preflight: [preflight] Some fatal errors occurred:
        [ERROR Swap]: running with swap on is not supported. Please disable swap
[preflight] If you know what you are doing, you can make a check non-fatal with `--ignore-preflight-errors=...`
To see the stack trace of this error execute with --v=5 or higher

preflight checkでつまずく。

running with swap on is not supported. Please disable swap

とのことなので、素直にswapをoffにする。

$ sudo /sbin/swapoff --all

そしてもう1度初期設定を実行する。

$ sudo kubeadm init --pod-network-cidr=192.168.0.0/16
[init] Using Kubernetes version: v1.16.2
[preflight] Running pre-flight checks
[preflight] Pulling images required for setting up a Kubernetes cluster
[preflight] This might take a minute or two, depending on the speed of your internet connection
[preflight] You can also perform this action in beforehand using 'kubeadm config images pull'
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Activating the kubelet service
[certs] Using certificateDir folder "/etc/kubernetes/pki"
[certs] Generating "ca" certificate and key
[certs] Generating "apiserver" certificate and key
[certs] apiserver serving cert is signed for DNS names [calicothehardway-001 kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] and IPs [1.2.3.4 127.0.0.1]
[certs] Generating "apiserver-kubelet-client" certificate and key
[certs] Generating "front-proxy-ca" certificate and key
[certs] Generating "front-proxy-client" certificate and key
[certs] Generating "etcd/ca" certificate and key
[certs] Generating "etcd/server" certificate and key
[certs] etcd/server serving cert is signed for DNS names [calicothehardway-001 localhost] and IPs [1.2.3.4 127.0.0.1 ::1]
[certs] Generating "etcd/peer" certificate and key
[certs] etcd/peer serving cert is signed for DNS names [calicothehardway localhost] and IPs [1.2.3.4 127.0.0.1 ::1]
[certs] Generating "etcd/healthcheck-client" certificate and key
[certs] Generating "apiserver-etcd-client" certificate and key
[certs] Generating "sa" key and public key
[kubeconfig] Using kubeconfig folder "/etc/kubernetes"
[kubeconfig] Writing "admin.conf" kubeconfig file
[kubeconfig] Writing "kubelet.conf" kubeconfig file
[kubeconfig] Writing "controller-manager.conf" kubeconfig file
[kubeconfig] Writing "scheduler.conf" kubeconfig file
[control-plane] Using manifest folder "/etc/kubernetes/manifests"
[control-plane] Creating static Pod manifest for "kube-apiserver"
[control-plane] Creating static Pod manifest for "kube-controller-manager"
[control-plane] Creating static Pod manifest for "kube-scheduler"
[etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests"
[wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory "/etc/kubernetes/manifests". This can take up to 4m0s
[apiclient] All control plane components are healthy after 13.003046 seconds
[upload-config] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
[kubelet] Creating a ConfigMap "kubelet-config-1.16" in namespace kube-system with the configuration for the kubelets in the cluster
[upload-certs] Skipping phase. Please see --upload-certs
[mark-control-plane] Marking the node calicothehardway-001 as control-plane by adding the label "node-role.kubernetes.io/master=''"
[mark-control-plane] Marking the node calicothehardway-001 as control-plane by adding the taints [node-role.kubernetes.io/master:NoSchedule]
[bootstrap-token] Using token: 9q8nf1.********************
[bootstrap-token] Configuring bootstrap tokens, cluster-info ConfigMap, RBAC Roles
[bootstrap-token] configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials
[bootstrap-token] configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token
[bootstrap-token] configured RBAC rules to allow certificate rotation for all node client certificates in the cluster
[bootstrap-token] Creating the "cluster-info" ConfigMap in the "kube-public" namespace
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy

Your Kubernetes control-plane has initialized successfully!

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 1.2.3.4:6443 --token 9q8nf1.******************** \
    --discovery-token-ca-cert-hash sha256:*******************************************************

注: ログ出力の一部記述を編集している

どうやらうまくいったようだ。引き続き、ログ出力に記述されている指示に従ってKubernetes clusterを起動させる準備をする。

$ mkdir -p $HOME/.kube
$ sudo cp -iv /etc/kubernetes/admin.conf $HOME/.kube/config
‘/etc/kubernetes/admin.conf’ -> ‘/home/user/.kube/config’
$ sudo chown -v $(id -u):$(id -g) $HOME/.kube/config
changed ownership of ‘/home/user/.kube/config’ from root:root to 11000:11000
$ kubectl get nodes -o wide
NAME                   STATUS     ROLES    AGE    VERSION   INTERNAL-IP      EXTERNAL-IP   OS-IMAGE                KERNEL-VERSION               CONTAINER-RUNTIME
calicothehardway-001   NotReady   master   113s   v1.16.2   1.2.3.4          <none>        CentOS Linux 7 (Core)   3.10.0-1062.1.2.el7.x86_64   docker://18.6.2

StatusがNotReadyとなっているが、これにはちゃんと理由があって、kubectl get nodeをやってみると、以下の出力内容によって説明されている。

...
  Ready            False   Wed, 13 Nov 2019 01:10:00 +0900   Wed, 13 Nov 2019 01:01:56 +0900   KubeletNotReady              runtime network not ready: NetworkReady=false reason:NetworkPluginNotReady message:docker: network plugin is not ready: cni config uninitialized
...

要はNetwork pluginを入れてないためにNotReadyということで、まぁそうだよねっていう感じ。なので、このまま作業を継続する。残りの作業はSlaveとなるノードでswapをoffにしてクラスターに追加していけば良い。

# 各Slaveノードで以下を実行する。
$ sudo /sbin/swapoff --all
$ sudo kubeadm join ... # 残りの引数はkubeadmの画面に出てきたものをコピペ

最後にもう1度kubectl get nodeをやって追加したSlaveノードが全部表示されているかを確認する。

$ kubectl get nodes
NAME                   STATUS     ROLES    AGE     VERSION
calicothehardway-001   NotReady   master   15m     v1.16.2
calicothehardway-002   NotReady   <none>   10m     v1.16.2
calicothehardway-003   NotReady   <none>   2m41s   v1.16.2
calicothehardway-004   NotReady   <none>   50s     v1.16.2
calicothehardway-005   NotReady   <none>   32s     v1.16.2

問題なさそう。Day1はKubernetes準備ということなので、ここまで。