Kubernetesのラボ、初期構築(後編)

この記事は約29分で読めます。
スポンサーリンク

この記事は「Kubernetesのラボ、初期構築(前編)」の続きとなります。

Kubernetesのラボ、初期構築(前編)
あくまでも試みレベルですが、「Kubernetes勉強記事」の連載を始めてみようと思います。 はじめに ラボの構築について、以下のリンクの記事を参考にさせていただきました。決して全ての手順が私の独自アイデアで完成できた訳ではあり...

これまでやったこと

前編が終わった段階のKubernetes環境構築はこんな感じ。

  • Masterノード(LoadBalancer以外)
  • Workerノード(1と2)

残ってる作業は以下となります。

  • LBノード(LoadBalancer)
  • MasterノードからLoadBalancerの初期設定

終わったら簡単な稼働確認を行います。

LB Nodeの設定

LB Nodeの設定です。

topology4

手順はMasterNodeと殆ど同じです。最後が違うだけ。

Kubenetes Repositoryの設定

/etc/yum.repos.d/kubernetes.repoを「作成」してください。

[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg
        https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg

KubeadmとDockerの導入

以下をコピペしてください。

yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum makecache fast -y
yum remove docker docker-common docker-selinux docker-engine -y
yum install docker-ce-17.06.0.ce-1.el7.centos -y
yum install kubectl-1.12.3-0.x86_64 -y
yum install kubelet-1.12.3-0.x86_64 -y
yum install kubeadm-1.12.3-0.x86_64 -y

docker-ceとkubeadmのインストールにバージョンを指定しているのがミソです。現時点でバージョンを指定しなければ、Dockerのバージョンが新しくて、以降のKubernetes init時にエラーが発生します。

とりあえずコピペしてください。

Serviceの初期設定

インストールしたDockerとKubeadmをsystemctlに登録&起動します。firewalldは停止します。ついでにswapをoffします。

systemctl restart docker && systemctl enable docker
systemctl restart kubelet && systemctl enable kubelet
systemctl stop firewalld && systemctl disable firewalld
swapoff -a
sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab

結果はこんな感じ。

[root@master ~]# systemctl restart docker && systemctl enable docker
Created symlink from /etc/systemd/system/multi-user.target.wants/docker.service to /usr/lib/systemd/system/docker.service.
[root@master ~]# systemctl restart kubelet && systemctl enable kubelet
Created symlink from /etc/systemd/system/multi-user.target.wants/kubelet.service to /etc/systemd/system/kubelet.service.
[root@master ~]# systemctl stop firewalld && systemctl disable firewalld
Removed symlink /etc/systemd/system/multi-user.target.wants/firewalld.service.
Removed symlink /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.
[root@master ~]# swapoff -a
[root@master ~]# sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab

以下を実行してiptablesを修正します。これをやらないと後述のjoinでエラーが発生します。

echo '1' > /proc/sys/net/bridge/bridge-nf-call-iptables

Masterのinit時に取得したコマンドを実行します(環境によってstringが違います)。このコマンドでMasterに参加します。つまり、初めてMasterと通信してます。

kubeadm join 192.168.1.80:6443 --token ef3cdn.70o8xcpksoech0eo --discovery-token-ca-cert-hash sha256:15c8eb4774268670a344c8b4d2b2fc891b0527e1049f5ef5e482b68d67d79e9e

うまくいけば、こんな感じになります。

[root@node1 ~]# kubeadm join 192.168.1.80:6443 --token ef3cdn.70o8xcpksoech0eo --discovery-token-ca-cert-hash sha256:15c8eb4774268670a344c8b4d2b2fc891b0527e1049f5ef5e482b68d67d79e9e
[preflight] running pre-flight checks
	[WARNING RequiredIPVSKernelModulesAvailable]: the IPVS proxier will not be used, because the following required kernel modules are not loaded: [ip_vs ip_vs_rr ip_vs_wrr ip_vs_sh nf_conntrack_ipv4] or no builtin kernel ipvs support: map[ip_vs:{} ip_vs_rr:{} ip_vs_wrr:{} ip_vs_sh:{} nf_conntrack_ipv4:{}]
you can solve this problem with following methods:
 1. Run 'modprobe -- ' to load missing kernel modules;
2. Provide the missing builtin kernel ipvs support

[discovery] Trying to connect to API Server "192.168.1.80:6443"
[discovery] Created cluster-info discovery client, requesting info from "https://192.168.1.80:6443"
[discovery] Requesting info from "https://192.168.1.80: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 "192.168.1.80:6443"
[discovery] Successfully established connection with API Server "192.168.1.80:6443"
[kubelet] Downloading configuration for the kubelet from the "kubelet-config-1.12" ConfigMap in the kube-system namespace
[kubelet] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[preflight] Activating the kubelet service
[tlsbootstrap] Waiting for the kubelet to perform the TLS Bootstrap...
[patchnode] Uploading the CRI Socket information "/var/run/dockershim.sock" to the Node API object "node1" as an annotation

This node has joined the cluster:
* Certificate signing request was sent to apiserver 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.

失敗したかもしれません。大丈夫です。

もし前回の記事から少し時間を置いて構築している場合、以下のメッセージがLBノード側で表示されてたかもしれません。

[kubelet] Downloading configuration for the kubelet from the "kubelet-config-1.12" ConfigMap in the kube-system namespace
Unauthorized

実は、このメッセージを表示させるために記事を分けたという意図があったのでした。

初回にMasterノードをinitした時に以下のコマンドをコピーしましたね。

kubeadm join 192.168.1.80:6443 --token ef3cdn.70o8xcpksoech0eo --discovery-token-ca-cert-hash sha256:15c8eb4774268670a344c8b4d2b2fc891b0527e1049f5ef5e482b68d67d79e9e

このtokenは24時間しか有効じゃないんです。以下のコマンドをMasterノードで実行してみてください。

[root@master ~]# kubeadm token list
TOKEN                     TTL         EXPIRES                USAGES                   DESCRIPTION                                                EXTRA GROUPS
ef3cdn.70o8xcpksoech0eo   <invalid>   2018-12-02T11:51:23Z   authentication,signing   The default bootstrap token generated by 'kubeadm init'.   system:bootstrappers:kubeadm:default-node-token

「EXPIRES」が、initコマンドを実行した際のトークンの有効期限です。この有効期限以降にjoinコマンドで同じトークンを使用しても、unauthorizedになります。

なので、このトークンは使えないので、もう一つトークンを作ります。

Masterノードで以下を実行してください。

[root@master ~]# kubeadm token generate
ghx3fc.d5u4tu7tm4dputkk
[root@master ~]# kubeadm token create ghx3fc.d5u4tu7tm4dputkk --print-join-command --ttl=0
kubeadm join 192.168.1.80:6443 --token ghx3fc.d5u4tu7tm4dputkk --discovery-token-ca-cert-hash sha256:15c8eb4774268670a344c8b4d2b2fc891b0527e1049f5ef5e482b68d67d79e9e

後は出力された結果のコマンドをLBノードで実行するだけです。(ちなみに–ttl=0とは有効期限なしという意味なので、本番で使用してはいけません)

[preflight] Some fatal errors occurred:
	[ERROR FileAvailable--etc-kubernetes-bootstrap-kubelet.conf]: /etc/kubernetes/bootstrap-kubelet.conf already exists
	[ERROR FileAvailable--etc-kubernetes-pki-ca.crt]: /etc/kubernetes/pki/ca.crt already exists
[preflight] If you know what you are doing, you can make a check non-fatal with `--ignore-preflight-errors=...`

今度はLBNode側で違うエラーが表示されました。これは初回のjoin時にファイルが作られていて、ゴミが残ってるからです。

以下のコマンドで、一度LBNode側をリセットします。(MasterNodeじゃなくてLBNodeでやること)

[root@nodelb ~]# kubeadm reset
[reset] WARNING: changes made to this host by 'kubeadm init' or 'kubeadm join' will be reverted.
[reset] are you sure you want to proceed? [y/N]: y
[preflight] running pre-flight checks
[reset] stopping the kubelet service
[reset] unmounting mounted directories in "/var/lib/kubelet"
[reset] no etcd manifest found in "/etc/kubernetes/manifests/etcd.yaml". Assuming external etcd
[reset] please manually reset etcd to prevent further issues
[reset] deleting contents of stateful directories: [/var/lib/kubelet /etc/cni/net.d /var/lib/dockershim /var/run/kubernetes]
[reset] deleting contents of config directories: [/etc/kubernetes/manifests /etc/kubernetes/pki]
[reset] deleting files: [/etc/kubernetes/admin.conf /etc/kubernetes/kubelet.conf /etc/kubernetes/bootstrap-kubelet.conf /etc/kubernetes/controller-manager.conf /etc/kubernetes/scheduler.conf]

これでリセットされたはずなので、再度joinコマンドを実行します。

[root@nodelb ~]# kubeadm join 192.168.1.80:6443 --token ghx3fc.d5u4tu7tm4dputkk --discovery-token-ca-cert-hash sha256:15c8eb4774268670a344c8b4d2b2fc891b0527e1049f5ef5e482b68d67d79e9e
[preflight] running pre-flight checks
	[WARNING RequiredIPVSKernelModulesAvailable]: the IPVS proxier will not be used, because the following required kernel modules are not loaded: [ip_vs_rr ip_vs_wrr ip_vs_sh nf_conntrack_ipv4 ip_vs] or no builtin kernel ipvs support: map[ip_vs:{} ip_vs_rr:{} ip_vs_wrr:{} ip_vs_sh:{} nf_conntrack_ipv4:{}]
you can solve this problem with following methods:
 1. Run 'modprobe -- ' to load missing kernel modules;
2. Provide the missing builtin kernel ipvs support

[discovery] Trying to connect to API Server "192.168.1.80:6443"
[discovery] Created cluster-info discovery client, requesting info from "https://192.168.1.80:6443"
[discovery] Requesting info from "https://192.168.1.80: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 "192.168.1.80:6443"
[discovery] Successfully established connection with API Server "192.168.1.80:6443"
[kubelet] Downloading configuration for the kubelet from the "kubelet-config-1.12" ConfigMap in the kube-system namespace
[kubelet] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[preflight] Activating the kubelet service
[tlsbootstrap] Waiting for the kubelet to perform the TLS Bootstrap...
[patchnode] Uploading the CRI Socket information "/var/run/dockershim.sock" to the Node API object "nodelb" as an annotation

This node has joined the cluster:
* Certificate signing request was sent to apiserver 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.

今回は正常に登録できたようですね。

MasterでLBNodeの登録を確認

Workerノードのときと同じです。

以下のコマンドでNodeの登録を確認します。

kubectl get node

結果は以下の出力になるはずです。

[root@master ~]# kubectl get node
NAME     STATUS   ROLES    AGE   VERSION
master   Ready    master   42h   v1.12.3
node1    Ready    <none>   41h   v1.12.3
node2    Ready    <none>   41h   v1.12.3
nodelb   Ready    <none>   64s   v1.12.3

重要なのは「master/node1/node2/nodelb」の全てが「Ready」になってることです。

繰り返しになりますが、ここまではWorkerノードをMasterに参加させる手順と同じでした。

ここからKubernetesのLoadBalancerとして使える「MetalLB」を導入していきます。

MetalLBの導入

前回の記事でも説明しましたが、MetalLBの導入については以下の記事を参考にさせていただきました。

>>Kubernetes on CentOS7

今回のラボでも上記の「MetalLBのデプロイ」のL2モードを参考に構築しています。

IPアドレスレンジは「192.168.1.85-192.168.1.89」としました。

[root@master ~]# cat metallb-l2.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  namespace: metallb-system
  name: config
data:
  config: |
    address-pools:
    - name: default
      protocol: layer2
      addresses:
      - 192.168.1.185-192.168.1.189

 

上記の記事ではtaint/tolerationの設定が紹介されていますが、node affinityで対応することも可能です。Flannel初期設定のセクションでtaint/tolerationはやったので、今回はnode affinityの設定を行ってみます。

既に上記の記事のapplyを行った方は、まずcontrollerを削除します。

[root@master ~]# kubectl get deployment -n metallb-system
NAME         DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
controller   1         1         1            1           94s
[root@master ~]# kubectl delete deployment controller -n metallb-system
deployment.extensions "controller" deleted

次に、nodelbにnode affinityに認識させるラベルを付与します。

kubectl label nodes nodelb node.role=lb

ラベルが付与されたかの確認は「kubectl describe node nodelb」で確認します。

[root@master ~]# kubectl describe node nodelb
Name:               nodelb
Roles:              <none>
Labels:             beta.kubernetes.io/arch=amd64
                    beta.kubernetes.io/os=linux
                    kubernetes.io/hostname=nodelb
                    node.role=lb
以下省略

ちなみに、以下のコマンドでもラベルだけを確認できます。

[root@master ~]# kubectl get nodes nodelb --show-labels
NAME     STATUS   ROLES    AGE   VERSION   LABELS
nodelb   Ready    <none>   50m   v1.12.3   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=nodelb,node.role=lb

metallb.yamlにnode affinityの設定を追加します。

      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: "node.role"
                operator: In
                values: ["lb"]

再度適用します。

[root@master ~]# kubectl apply -f metallb.yaml
namespace/metallb-system unchanged
serviceaccount/controller unchanged
serviceaccount/speaker unchanged
clusterrole.rbac.authorization.k8s.io/metallb-system:controller unchanged
clusterrole.rbac.authorization.k8s.io/metallb-system:speaker unchanged
role.rbac.authorization.k8s.io/config-watcher unchanged
clusterrolebinding.rbac.authorization.k8s.io/metallb-system:controller unchanged
clusterrolebinding.rbac.authorization.k8s.io/metallb-system:speaker unchanged
rolebinding.rbac.authorization.k8s.io/config-watcher unchanged
daemonset.apps/speaker unchanged
deployment.apps/controller created

これでnodelbにcontrollerのPODが起動しました。

[root@master ~]# kubectl get pod -n metallb-system -o wide
NAME                          READY   STATUS    RESTARTS   AGE   IP             NODE     NOMINATED NODE
controller-567586546b-tg9rv   1/1     Running   0          14s   10.244.3.2     nodelb   <none>
speaker-5vxsx                 1/1     Running   0          17m   192.168.1.83   nodelb   <none>
speaker-df48d                 1/1     Running   0          17m   192.168.1.82   node2    <none>
speaker-hfpsq                 1/1     Running   0          17m   192.168.1.81   node1    <none>

簡単な動作確認

これでKubernetesラボ環境は終了です。

ざっくりと動作確認をしてみましょう。

この時点では「deploymentとは?」とか「podとは?」とかの説明を一切していない状態なので、とりあえず「ほぉ〜」と思っていただければ結構です。

この時点の学習レベルだと「環境を汚さないか?削除できないか怖い!」という不安があると思いますので、作成したオブジェクトの削除まで全部やるのでご安心ください。

全てMasterノード(192.168.1.80)で行います。

まず、Kubernetesのオフィシャルサイトでも使われている「kubernetes-bootcamp」イメージをデプロイします。このイメージを使う理由は以下の通り。

  • 初めからweb-serverが入ってるので確認しやすい
  • トップページにpod名を表示する機能があるので、LBの確認がしやすい
  • execでcontainerそのものに入った後にip -aができる。iproutingが予め入ってる。ネットワークの確認がしやすい
[root@master ~]# kubectl run kubernetes-bootcamp --image=gcr.io/google-samples/kubernetes-bootcamp:v1 --port=8080
kubectl run --generator=deployment/apps.v1beta1 is DEPRECATED and will be removed in a future version. Use kubectl create instead.
deployment.apps/kubernetes-bootcamp created

これだけで、WebServerが動きました!地味に嬉しい!

[root@master ~]# kubectl get pod -o wide
NAME                                   READY   STATUS    RESTARTS   AGE     IP           NODE    NOMINATED NODE
kubernetes-bootcamp-598f57b95c-4g8f7   1/1     Running   0          7m16s   10.244.2.3   node2   <none>

上の「Node」列を見ると「node2」との記載があります。つまり、「たまたま」node2上で動きました。

次に外部(192.168.1.0/24のどのホストからでも)アクセスできるように設定します。

以下のファイルをbootcamp.yamlとして保存してください。

apiVersion: v1
kind: Service
metadata:
  name: kubernetes-bootcamp
spec:
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 8080
  selector:
    run: kubernetes-bootcamp
  type: LoadBalancer

適用します。

[root@master ~]# kubectl apply -f bootcamp.yaml
service/kubernetes-bootcamp created

これでMetalLB設定時のIPレンジからIPが一つ払い出されてLBのVIPとしての役割を担ってるはずです。

確認します。

[root@master ~]# kubectl get svc -o wide
NAME                  TYPE           CLUSTER-IP       EXTERNAL-IP     PORT(S)        AGE   SELECTOR
kubernetes            ClusterIP      10.96.0.1        <none>          443/TCP        43h   <none>
kubernetes-bootcamp   LoadBalancer   10.104.143.241   192.168.1.185   80:32070/TCP   5s    run=kubernetes-bootcamp

「EXTERNAL-IP」の列が、払い出されたIPです。

つまり、今回は「192.168.1.185」が払い出されました。

192.168.1.0/24のパソコンから「http://192.168.1.185」にアクセスします。(http://192.168.1.185:32070じゃないです)

bootcamp1

上記のメッセージがでたらOKです。kubernetes-bootcamp-XXの部分は文字列的に違うかもしれませんが、この画面が表示されたということは、Webサーバーの確認ができたということです。

 

では、後処理をします。

まずServiceを削除します。

[root@master ~]# kubectl get svc
NAME                  TYPE           CLUSTER-IP       EXTERNAL-IP     PORT(S)        AGE
kubernetes            ClusterIP      10.96.0.1        <none>          443/TCP        43h
kubernetes-bootcamp   LoadBalancer   10.104.143.241   192.168.1.185   80:32070/TCP   12m
[root@master ~]# kubectl delete svc kubernetes-bootcamp
service "kubernetes-bootcamp" deleted
[root@master ~]# kubectl get svc
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   43h

次にDeploymentを削除します。

[root@master ~]# kubectl get deployment
NAME                  DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
kubernetes-bootcamp   1         1         1            1           14m
[root@master ~]# kubectl delete deployment kubernetes-bootcamp
deployment.extensions "kubernetes-bootcamp" deleted
[root@master ~]# kubectl get deployment
No resources found.

これで検証用に作ったオブジェクトが全て削除されました。

当然、再度同じオブジェクトを作ることもできます。

この時点のスナップショットを取ってください

これでラボ環境が出来上がりました!

嬉しくないですか?私だけでしょうか・・・

喜び勇んで色々試す前に、全4VMのスナップショットを取っておいてください。これで最悪色々試して壊したときにも元に戻れます。

 

ここまで色々やりました。多分90%くらいの作業は「自分が何をやってるかわからない」状態だったと思います。

次回から色々内容を解説する予定です。

コメント

タイトルとURLをコピーしました