Project CalicoをKubernetesで使ってみる:構築編
今回は実際にCalicoを使用してKubernetesのネットワークを構築します。Kubernetesはコンテナオーケストレーションツールとして非常に盛り上がりを見せています。CalicoはKubernetesとの統合も活発に進められており、以前に紹介したようにセキュリティポリシーにも対応していることから、コンテナのネットワークおよびセキュリティとして使用される場面が多くなってくると思われます。
Kubernetesとは
Kubernetesはコンテナ化されたアプリケーションの自動デプロイやオートスケーリング、管理を行うオープンソースソフトウェアです。元々はGoogleがデータセンターでコンテナを管理するために開発したBorgというソフトウェアをOSS化したものになります。Kubernetesではネットワークの管理やデプロイを各ネットワークプラグインに任せており、Container Networking Interface(CNI)として実装されます。CNIプラグインの一つとしてCalicoが提供されているため、Kubernetesのコンテナネットワークとして動作させることを可能としています。
構築する環境について
バージョン情報
今回構築する環境では以下のバージョンを使用しています。
バージョン Calico v3.0 Calico CLI Tool v2.0.1 Kubernetes v1.9.4 Docker 17.12.1-ce kubeadm v1.9.4
クラスタ構成
今回構築するKubernetes環境は、1台のマスターと2台のノード、合計3台で構成するシンプルなKubernetesクラスタになります。Kubernetesは最小1台で構成できますが、せっかくCalicoを使ってルーティングネットワークを組むので3台構成にしています。筆者の環境ではUbuntu16.04をインストールした物理サーバー上にKVMで仮想マシンを3台立てており、1つのLinux Bridgeに接続してL2で通信できるようにしています。仮想マシンのOSとしてもUbuntu16.04をインストールしています。
Kubernetes構築
Kubeadmのインストール
今回は構築にkubeadmというツールを使用しました。kubeadmはKubernetesのアップストリームで開発されているKubernetes構築ツールです。kubeadm自体のインストール手順はInstalling kubeadmに詳しく書かれているので割愛します。
Kubernetesクラスタの構築
Masterの構築
まず始めにマスターの構築から行います。 kubeadm init
コマンドによりマスターを初期化します。コマンド実行時にさまざまなオプションを渡すことができますが、ここではCalicoによって管理されるPodに割り当てられるIPアドレスのCIDRに 192.168.0.0/16
を指定しています。
k8s-master~$ sudo kubeadm init --pod-network-cidr=192.168.0.0/16 --ignore-preflight-errors=Swap [init] Using Kubernetes version: v1.9.4 [init] Using Authorization modes: [Node RBAC] [preflight] Running pre-flight checks. [WARNING SystemVerification]: docker version is greater than the most recently validated version. Docker version: 17.12.1-ce. Max validated version: 17.03 [WARNING Swap]: running with swap on is not supported. Please disable swap [WARNING FileExisting-crictl]: crictl not found in system path [preflight] Starting the kubelet service [certificates] Generated ca certificate and key. [certificates] Generated apiserver certificate and key. [certificates] apiserver serving cert is signed for DNS names [k8s-master kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] and IPs [10.96.0.1 172.16.0.10] [certificates] Generated apiserver-kubelet-client certificate and key. [certificates] Generated sa key and public key. [certificates] Generated front-proxy-ca certificate and key. [certificates] Generated front-proxy-client certificate and key. [certificates] Valid certificates and keys now exist in "/etc/kubernetes/pki" [kubeconfig] Wrote KubeConfig file to disk: "admin.conf" [kubeconfig] Wrote KubeConfig file to disk: "kubelet.conf" [kubeconfig] Wrote KubeConfig file to disk: "controller-manager.conf" [kubeconfig] Wrote KubeConfig file to disk: "scheduler.conf" [controlplane] Wrote Static Pod manifest for component kube-apiserver to "/etc/kubernetes/manifests/kube-apiserver.yaml" [controlplane] Wrote Static Pod manifest for component kube-controller-manager to "/etc/kubernetes/manifests/kube-controller-manager.yaml" [controlplane] Wrote Static Pod manifest for component kube-scheduler to "/etc/kubernetes/manifests/kube-scheduler.yaml" [etcd] Wrote Static Pod manifest for a local etcd instance to "/etc/kubernetes/manifests/etcd.yaml" [init] Waiting for the kubelet to boot up the control plane as Static Pods from directory "/etc/kubernetes/manifests". [init] This might take a minute or longer if the control plane images have to be pulled. [apiclient] All control plane components are healthy after 48.001818 seconds [uploadconfig]?Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace [markmaster] Will mark node k8s-master as master by adding a label and a taint [markmaster] Master k8s-master tainted and labelled with key/value: node-role.kubernetes.io/master="" [bootstraptoken] Using token: 658fea.b67a9ffdaced182a [bootstraptoken] Configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials [bootstraptoken] Configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token [bootstraptoken] Configured RBAC rules to allow certificate rotation for all node client certificates in the cluster [bootstraptoken] Creating the "cluster-info" ConfigMap in the "kube-public" namespace [addons] Applied essential addon: kube-dns [addons] Applied essential addon: kube-proxy Your Kubernetes master 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/ You can now join any number of machines by running the following on each node as root: kubeadm join --token 77d3cb.a4344218b6afb535 172.16.0.10:6443 --discovery-token-ca-cert-hash sha256:d87774ddd2e342e86cf9092d294f9fedb85639a1812629f5f6b2c079ff4b67fc
初期化処理が完了すると「Your Kubernetes master has initialized successfully!」というメッセージとともに、kubectlを使用するための設定方法とノードを追加するためのコマンドが出力されます。これはノードの構築時に使用するのでメモしておいてください。
kubectlを使うための設定としてadmin.confが作成されているので、ホームディレクトリの.kubeというディレクトリに移動し、ファイルの所有権を変更します。
k8s-master~$ mkdir -p $HOME/.kube k8s-master~$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config k8s-master~$ sudo chown $(id -u):$(id -g) $HOME/.kube/config
これでkubectlコマンドが使用できるようになりました。ノードの状態を確認してみます。以下のようにノードの状態が取得できれば成功です。
k8s-master~$ kubectl get nodes NAME STATUS ROLES AGE VERSION k8s-master NotReady master 2m v1.9.4
この時点ではネットワークプラグインをインストールしていないのでノードのSTATUSがNotReadyとなっています。
それでは、ネットワークプラグインをインストールします。通常、Podネットワークはクラスタごとに1つのCNIプラグインが必要になりますのでCalicoを選択します。Project Calicoのドキュメントで サンプル の設定が用意されているので、ここではそのサンプルを使いたいと思います。
マスターの構築時に --pod-network-cider=192.168.0.0/16 を指定しました。これは、calico.yamlの220行目のCALICO_IPV4POOL_CIDRの値と揃えています。その他のCalicoノードの設定パラメータは[ドキュメントのConfiguring calico/nodeに全て記載されているので必要に応じて修正します。今回はサンプルのまま設定します。インストール方法は以下のようにサンプルの設定ファイルを適用するだけです。
k8s-master~$ kubectl apply -f https://docs.projectcalico.org/v3.0/getting-started/kubernetes/installation/hosted/kubeadm/1.7/calico.yaml
コマンドが問題なく終了したら、Podの状態を確認します。 kubectl get pods --all-namespaces
で全てのPodのSTATUSがRunningになっていることを確認します。Kubernetes本体のPodやCalicoのPodはkube-systemというネームスペースで起動されますので、 --all-namespace
か -n kube-system
というオプションを指定する必要があります。
NAMESPACE NAME READY STATUS RESTARTS AGE kube-system calico-etcd-dxb8s 1/1 Running 0 3m kube-system calico-kube-controllers-559b575f97-29m7j 1/1 Running 0 3m kube-system calico-node-bggsx 2/2 Running 0 3m kube-system etcd-k8s-master 1/1 Running 0 4m kube-system kube-apiserver-k8s-master 1/1 Running 0 3m kube-system kube-controller-manager-k8s-master 1/1 Running 0 3m kube-system kube-dns-6f4fd4bdf-8xwwz 3/3 Running 0 4m kube-system kube-proxy-f5mpg 1/1 Running 0 4m kube-system kube-scheduler-k8s-master 1/1 Running 0 3m
すべて正常に起動できると、ノードのSTATUSがReadyになっているのが確認できます。
k8s-master~$ kubectl get nodes NAME STATUS ROLES AGE VERSION k8s-master Ready master 5m v1.9.4
以上でマスターの構築は完了です。
ノードの追加
マスターが構築できたので、続いてノードを追加していきます。ノードにも事前にkubeadmなどのパッケージをインストールしておいてください。
マスターの構築時にメモしたノードを追加するコマンドを用意してください。ノードにログインし、メモしたコマンドを実行します。
k8s-node-01~$ sudo kubeadm join --token 77d3cb.a4344218b6afb535 172.16.0.10:6443 --discovery-token-ca-cert-hash sha256:d87774ddd2e342e86cf9092d294f9fedb85639a1812629f5f6b2c079ff4b67fc --ignore-preflight-errors=Swap [preflight] Running pre-flight checks. [WARNING SystemVerification]: docker version is greater than the most recently validated version. Docker version: 17.12.1-ce. Max validated version: 17.03 [WARNING Swap]: running with swap on is not supported. Please disable swap [WARNING FileExisting-crictl]: crictl not found in system path [preflight] Starting the kubelet service [discovery] Trying to connect to API Server "172.16.0.10:6443" [discovery] Created cluster-info discovery client, requesting info from "https://172.16.0.10:6443" [discovery] Requesting info from "https://172.16.0.10:6443" again to validate TLS against the pinned public key [discovery] Cluster info signature and contents are valid and TLS certificate validates against pinned roots, will use API Server "172.16.0.10:6443" [discovery] Successfully established connection with API Server "172.16.0.10:6443" This node has joined the cluster: * Certificate signing request was sent to master and a response was received. * The Kubelet was informed of the new secure connection details. Run 'kubectl get nodes' on the master to see this node join the cluster.
マスターで kubectl get pods --all-namespaces
を実行して、全てのPodが起動できたらノードの構築が完了です。もう1台のノードk8s-node-02でも同じようにコマンドを実行し、全てのPodが起動できたらノードのSTATUSがReadyになっておりKubernetesクラスタの構築は完了です。
k8s-master~$ kubectl get nodes NAME STATUS ROLES AGE VERSION k8s-master Ready master 9m v1.9.4 k8s-node-01 Ready <none> 3m v1.9.4 k8s-node-02 Ready <none> 1m v1.9.4
動作の確認
CNIプラグインとしてCalicoを指定しました。Calicoを使用している場合、実際にはどのようなPodが動作しているのか見ていきます。
CalicoのコンポーネントとしてFelixやBIRD、etcdなどがありますが、これらはKubernetesのPodとしてkube-systemというネームスペースで起動します。CalicoのPodを確認するにはkube-systemというネームスペースを指定してPodの情報を取得します。
k8s-master~$ kubectl get pods -n kube-system -o wide NAME READY STATUS RESTARTS AGE IP NODE calico-etcd-dxb8s 1/1 Running 0 9m 172.16.0.10 k8s-master calico-kube-controllers-559b575f97-29m7j 1/1 Running 0 9m 172.16.0.10 k8s-master calico-node-2mttf 2/2 Running 0 3m 172.16.0.11 k8s-node-01 calico-node-6snck 2/2 Running 1 1m 172.16.0.12 k8s-node-02 calico-node-bggsx 2/2 Running 0 9m 172.16.0.10 k8s-master etcd-k8s-master 1/1 Running 0 9m 172.16.0.10 k8s-master kube-apiserver-k8s-master 1/1 Running 0 9m 172.16.0.10 k8s-master kube-controller-manager-k8s-master 1/1 Running 0 9m 172.16.0.10 k8s-master kube-dns-6f4fd4bdf-8xwwz 3/3 Running 0 9m 192.168.235.193 k8s-master kube-proxy-22gs4 1/1 Running 0 1m 172.16.0.12 k8s-node-02 kube-proxy-f5mpg 1/1 Running 0 9m 172.16.0.10 k8s-master kube-proxy-tc24n 1/1 Running 0 3m 172.16.0.11 k8s-node-01 kube-scheduler-k8s-master 1/1 Running 0 9m 172.16.0.10 k8s-master
CalicoのPodが5つ動作しているのがわかります。Calicoが使用するcalico-etcdがマスターで動作しています。calico-kube-controllersはkubernetesのネットワークポリシーやネームスペース、ラベルなどを監視し、etcdに書き込みます。そして、calico-nodeというPod内でFelixやBIRDといったプロセスが各ノードで動作しており、calico-etcdの情報をノードの設定に反映します。
Calico CLI Tool
Calicoノードの状態の確認や様々な設定を行ったりするために、Calico CLI Toolと呼ばれるクライアントツールが用意されています。Calico CLI Toolを使用するには、ソースコードからビルドするかGitHubからバイナリファイルをダウンロードして実行権限を付与します。
k8s-master~$ wget https://github.com/projectcalico/calicoctl/releases/download/v2.0.1/calicoctl k8s-master~$ chmod +x calicoctl
calicoctlを実行するにはetcdエンドポイントなどの値をcalicoctl.cfgという設定ファイルか環境変数でコマンドに渡す必要があります。ここではcalicoctl.cfgを使用します。
まず、calicoctl.cfgのファイルを置くディレクトリを作成します。calicoctlはデフォルトで /etc/calico/
を参照するようになっているので、このディレクトリを作成します。
k8s-master~$ sudo mkdir /etc/calico
calicoctl.cfgを作成します。
k8s-master~$ sudo vim /etc/calico/calicoctl.cfg
以下のようにYamlで記述し保存してください。etcdEndopointsはcalico.yamlの17行目に定義されているIPアドレスを設定します。etcdが冗長化され複数台ある場合には、カンマで区切って複数のIPアドレスを設定します。
apiVersion: projectcalico.org/v3 kind: CalicoAPIConfig metadata: spec: datastoreType: "etcdv3" etcdEndpoints: "http://10.96.232.136:6666"
これでcalicoctlを使用する準備が整いましたので、実際にコマンドを実行してCalicoノードを取得してみます。以下のように、Calicoノードの情報が取得できれば正しく動作しています。
k8s-master~$ ./calicoctl get node -o wide NAME ASN IPV4 IPV6 k8s-master (unknown) 172.16.0.10/16 k8s-node-01 (unknown) 172.16.0.11/16 k8s-node-02 (unknown) 172.16.0.12/16
--helpオプションを使用すれば様々な使い方を知ることができます。ぜひ色々見て使いこなしてください。
Usage: calicoctl [options] <command> [<args>...] create Create a resource by filename or stdin. replace Replace a resource by filename or stdin. apply Apply a resource by filename or stdin. This creates a resource if it does not exist, and replaces a resource if it does exists. delete Delete a resource identified by file, stdin or resource type and name. get Get a resource identified by file, stdin or resource type and name. convert Convert config files between different API versions. ipam IP address management. node Calico node management. version Display the version of calicoctl. Options: -h --help Show this screen. -l --log-level=<level> Set the log level (one of panic, fatal, error, warn, info, debug) [default: panic] Description: The calicoctl command line tool is used to manage Calico network and security policy, to view and manage endpoint configuration, and to manage a Calico node instance. See 'calicoctl <command> --help' to read about a specific subcommand.
アプリケーションのデプロイと疎通確認
Nginxアプリケーションのデプロイ
KubernetesとCalicoの環境が構築できたので実際にNginxのアプリケーションをデプロイしてみます。KubernetesのマスターにログインしてNginxのPodを起動します。--replicas=2とすることでNginxのPodを2つ起動しています。
k8s-master~$ kubectl run my-nginx --image=nginx --replicas=2 --port=80 deployment "my-nginx" created
Podが起動できたか確認します。
k8s-master~$ kubectl get pods NAME READY STATUS RESTARTS AGE my-nginx-9d5677d94-48pmz 1/1 Running 0 31s my-nginx-9d5677d94-z655m 1/1 Running 0 32s
STATUSがRunningになっていれば正しく起動できています。
疎通確認
NginxのPodがデプロイできたので、クラスター内部からアクセスできることを確認してみます。cURLがインストールされているPodを新たに起動して、NginxのPod IP宛にリクエストしてみます。まず、NginxのPod IPを確認します。--replicas=2を指定したので2つのPod IPが確認できます。
k8s-master~$ kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE my-nginx-9d5677d94-48pmz 1/1 Running 0 1m 192.168.154.193 k8s-node-01 my-nginx-9d5677d94-z655m 1/1 Running 0 1m 192.168.44.193 k8s-node-02
cURLがインストールされているPodを立ち上げます。起動と同時にPod内のプロンプトに入ることができます。--rmオプションを指定することで、プロンプトからCtrl+Cで抜けると同時にこのPodは削除されます。
それではNginxのPod IPにcurlでリクエストを投げてみます。まず、k8s-node-01上の192.168.154.193宛にリクエストします。
k8s-master~$ kubectl run curl --image=radial/busyboxplus:curl -i --tty --rm If you don't see a command prompt, try pressing enter. [ root@curl-545bbf5f9c-4bxsq:/ ]$ curl 192.168.154.193 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h2>Welcome to nginx!</h2> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html>
同じようにk8s-node-02上の192.168.44.193にもリクエストしてNginxからレスポンスが返ってくればCalicoによるクラスターネットワークが正常に動作しています。
[ root@curl-545bbf5f9c-4bxsq:/ ]$ curl 192.168.44.193 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h2>Welcome to nginx!</h2> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html>
最後にPodへの経路情報を確認してみましょう。まず、マスターからcalicoctlコマンドを使用してPodの名前、IPアドレス、インターフェース名の紐付きを確認します。CalicoではPodのインターフェースのことをワークロードエンドポイントと呼んでおり、取得するリソース名としてworkloadEndpointを指定しています。取得できる情報が多いので-oオプションを使用して表示するカラムを整形しています。
k8s-master~$ ./calicoctl get workloadEndpoint -o custom-columns=NODE,WORKLOAD,NETWORKS,INTERFACE NODE WORKLOAD NETWORKS INTERFACE k8s-node-01 my-nginx-9d5677d94-48pmz 192.168.154.193/32 calieafb5bf2e52 k8s-node-02 my-nginx-9d5677d94-z655m 192.168.44.193/32 calie29c2d4b309
my-nginx-9d5677d94-48pmzというNginxのPodがIPアドレス192.168.154.193が割り当てられてk8s-node-01上で動作しています。
k8s-node-01にログインしてPodへのルーティングを見てみましょう。NginxのPod宛である192.168.154.193への通信がcalieafb5bf2e52というインターフェースにホストルーティングされていることが確認できます。
k8s-node-01~$ route Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface default 172.16.0.1 0.0.0.0 UG 0 0 0 enp0s3 172.16.0.0 * 255.255.0.0 U 0 0 0 enp0s3 172.17.0.0 * 255.255.0.0 U 0 0 0 docker0 192.168.44.192 172.16.0.12 255.255.255.192 UG 0 0 0 tunl0 192.168.154.192 * 255.255.255.192 U 0 0 0 * 192.168.154.193 * 255.255.255.255 UH 0 0 0 calieafb5bf2e52 192.168.235.192 172.16.0.10 255.255.255.192 UG 0 0 0 tunl0
以上でCalicoおよびKubernetesの動作確認は終了です。
今回はCalicoとKubernetesの環境を構築し実際にNginxのアプリケーションを起動して疎通確認まで行いました。これでネットワークプラグインとしてのCalicoの振る舞いやコンテナネットワークのイメージができたと思います。次回は今回構築した環境を使用して、Calicoの代表的なセキュリティ機能であるネットワークポリシーを使用してみます。
連載バックナンバー
Think ITメルマガ会員登録受付中
全文検索エンジンによるおすすめ記事
- Kubernetes環境を構築して、実際にコンテナを動かしてみよう
- KubernetesのマニフェストをMagnumで実行する
- Kubernetes環境の選択肢
- Oracle Cloud Hangout Cafe Season5 #3「Kubernetes のセキュリティ」(2022年3月9日開催)
- Kubernetesの基礎
- Oracle Cloud Hangout Cafe Season7 #1「Kubnernetes 超入門」(2023年6月7日開催)
- 「Inspektor Gadget」でKubernetesクラスタをデバッグする
- Openstack Magnumの環境を構築する
- KubernetesのDiscovery&LBリソース(その1)
- RancherのCatalog機能を詳細に見てみる