はじめに
-
Amazon EC2でCentOSにKubernetesを構築する(前編) ここ
Kubernetesのインストール~Dashboard導入まで -
Amazon EC2でCentOSにKubernetesを構築する(後編)
Dockerイメージの作成~サービスの公開まで
Kubernetes(くーばねぃてす)はコンテナーとなっているアプリケーションをデプロイするプラットフォームです。Kubernetes自体にはコンテナーの機能は持っておらず、外部のコンテナーを使用するようになっていますが、大抵はDockerが使用されます。この記事でもDockerを使用します。
クラウドサービスでもKubernetesのサービス、KaaS(Kubernetes as a Service)を提供し始めており、Kubernetesの最初の開発であったGoogleが提供しているGoogle Cloud Platformはもちろん、Microsoft Azureでも提供されています。また、Amazonでも去年の11月にEKSが発表されて(まだメニューには無いようですが)、もはやKubernetesを1から手で構築する必要性は今後薄くなるのかもしれませんが、Kubernetesの機能をちょっと試してみたり、内部の動作を見たい場合には、手で構築する価値もあるでしょう。
Amazon EC2インスタンスで構築するのが少しやっかいである理由は、minikubeで構築できない(仮想ネットワークにVirtual Box が使えない)ことにあると思います。
この記事では、よくあるローカルPCにminikubeやUbuntuではなく、(RedHatを想定して)CentOS7で上、とにかくKubernetesで何か始められるところまで構築します。
環境
Workerノードは最低1つあれば良いのですが、clusterができる、ということを見るために2つ用意しました。またDocker private repositoryは、この記事では別マシンにしてしまいましたが、Masterノードと同一マシンで良いです。
- サーバー構成
名前(兼hostname) | 役割 | IPアドレス |
---|---|---|
kube-master | Masterノード | 172.26.22.85 |
kube-node1 | Workerノード1 | 172.26.22.71 |
kube-node2 | Workerノード2 | 172.26.22.99 |
docker-repo | Docker private repository | 172.26.22.6 |
- コンポーネントのバージョン
名前 | バージョン | 補足 |
---|---|---|
OS | CentOS 7.4 | |
Kubernetes | 1.10 | 2018年4月時点での最新 |
Docker | 1.13.1 | |
flannel | 0.91 | 0.90ではバグあり |
事前準備 [全ノード]
host名の変更とhostsファイルを編集する
Kubernetesはお互いのノードをhost名で解決するので、hostnameを変更しておきます。
- Masterノードの場合
# hostnamectl set-hostname kube-master
CentOS7では、hostnameの変更にOSの再起動が不要になりました。SSHのセッションを再作成すれば、host名の変更が反映されているのを確認できます。
hostsファイルに追加しておきます。
# vi /etc/hosts
172.26.22.85 kube-master
- Workerノード1の場合
Masterノードと同様ですが、自分自身のhost名もhostsファイルに追加しておきます。
# hostnamectl set-hostname kube-node1
# vi /etc/hosts
172.26.22.85 kube-master
172.26.22.71 kube-node1
- Workerノード2の場合
# hostnamectl set-hostname kube-node2
# vi /etc/hosts
172.26.22.85 kube-master
172.26.22.99 kube-node2
Dockerのインストール [全ノード]
Dockerのインストール
1.11以上が必要です。CentOS7.4でインストールできる最新は1.13.1なので、このバージョンにしました。
# yum install docker
# systemctl enable docker && systemctl start docker
HTTPプロキシーを設定するには? Service Unitファイルに環境変数を追加します。 NO_PROXY にはprivate repositoryのIPアドレスを加えておきます。※注1 NO_PROXY にはCIDR記法で書けない。※注2 複数ある場合はカンマ区切り。
|
確認する
# docker info | grep -i version
WARNING: You're not using the default seccomp profile
Server Version: 1.13.1
containerd version: (expected: aa8187dbd3b7ad67d8e5e3a15115d3eef43a7ed1)
runc version: N/A (expected: 9df8b306d01f59d3a8029be411de015b7304dd8f)
init version: N/A (expected: 949e6facb77383876aeff8a6944dde66b3089574)
Kernel Version: 3.10.0-693.21.1.el7.x86_64
# docker info | grep -i driver
WARNING: You're not using the default seccomp profile
Storage Driver: overlay2
Logging Driver: journald
Cgroup Driver: systemd
docker info | grep -i driver
の結果は、後で使用するのでメモっておきます。
Dockerのprivate repositoryへアクセスできるようにする
docker pull
はデフォルトでhttps
になるので、private repositoryに対してはhttp
でアクセスするように設定しておきます。
※注1 --insecure-registry
はCIDR記法で書けない。
※注2 =
(イコール)いらない
※注3 INSECURE_REGISTRY
というシェルの変数はなくなったようなので、OPTIONS
に加えます。
※注4 jsonに入れる、という記述もありますが、それは docker-ce のようです。
# vi /etc/sysconfig/docker
OPTIONS='--selinux-enabled --log-driver=journald --signature-verification=false'
↓
OPTIONS='--selinux-enabled --log-driver=journald --signature-verification=false --insecure-registry 172.26.22.6:5000'
Service Unitファイルを直接書き変えたので、リロードして再起動します。
# systemctl daemon-reload && systemctl restart docker
Kubernetesのインストール [全ノード]
iptablesの編集
# cat <<EOF > /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
# sysctl --system
インストール
yumレポジトリーからパッケージを取得してインストールするため、自動的に最新になります。2018年4月時点では1.10でした。また、setenforce 0
でSELINUXを無効にしておきます。
# cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-\$basearch
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
EOF
# setenforce 0
# yum install kubelet kubeadm kubectl
HTTPプロキシーを設定するには? /etc/yum.conf に追加します。
|
swap無効&cgroup設定
# vi /etc/systemd/system/kubelet.service.d/90-local-extras.conf
Environment="KUBELET_EXTRA_ARGS=--fail-swap-on=false"
Environment="KUBELET_CGROUP_ARGS=--cgroup-driver=systemd"
--cgroup-driver
の値は、Dockerインストール時のdocker info | grep -i driver
で出力されて値にします。CentOSなら大抵systemd
でしょう。
起動
# systemctl daemon-reload
# systemctl enable kubelet && systemctl start kubelet
確認
# kubectl version
Client Version: version.Info{Major:"1", Minor:"10", GitVersion:"v1.10.0", GitCommit:"fc32d2f3698e36b93322a3465f63a14e9f0eaead", GitTreeState:"clean", BuildDate:"2018-03-26T16:55:54Z", GoVersion:"go1.9.3", Compiler:"gc", Platform:"linux/amd64"}
The connection to the server localhost:8080 was refused - did you specify the right host or port?
この段階では、まだapiserverへの接続はエラーが出ます。
kubeadm [Masterノードのみ]
cgroupの設定
--cgroup-driver
の値は、Dockerインストール時の docker info | grep -i driver
で出力されて値にします。初期設定値は systemd
になっているはずですが、そうなっていない場合は変更しておきます。
# vi /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
Environment="KUBELET_CGROUP_ARGS=--cgroup-driver=systemd"
インストール
# kubeadm init \
--pod-network-cidr=10.244.0.0/16 \
--apiserver-advertise-address=172.26.22.85
内部仮想ネットワークにflannelを使う場合は、マニュアルの書かれている通り--pod-network-cidr
にアドレスを指定する必要があります。--apiserver-advertise-address
にMasterノードのアドレスを指定します。
HTTPプロキシーを設定するには?kubeadm init では外に接続するため、環境変数http_proxy, https_proxy, no_proxy 入れておきます。※注1 環境変数名は小文字。CIDR記法で書ける。 ※注2 private networkのIPアドレスも入れておくこと!
|
標準出力で出る最後の行は、Workerノードを追加するコマンドであるため、メモっておきます。
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 172.26.22.85:6443 --token ddpdzf.s89pe0whxm0osqoc --discovery-token-ca-cert-hash sha256:ca6dcf315312663170f72cf081604b6635e7ad98bb3440656d43d6ed5cd34d0e
トークンの有効期限と再発行は? トークンの有効期限は24時間です。有効期限が切れた場合は、再発行できます。
|
kubeconfig
kubeadm init
で出力された通り、kubeadm
コマンドを使えるようにしておきます。
# mkdir -p $HOME/.kube
# cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
# chown $(id -u):$(id -g) $HOME/.kube/config
もしくは、
# vi ~/.bash_profile
export KUBECONFIG=/etc/kubernetes/admin.conf
確認
# kubectl version
Client Version: version.Info{Major:"1", Minor:"10", GitVersion:"v1.10.0", GitCommit:"fc32d2f3698e36b93322a3465f63a14e9f0eaead", GitTreeState:"clean", BuildDate:"2018-03-26T16:55:54Z", GoVersion:"go1.9.3", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"10", GitVersion:"v1.10.0", GitCommit:"fc32d2f3698e36b93322a3465f63a14e9f0eaead", GitTreeState:"clean", BuildDate:"2018-03-26T16:44:10Z", GoVersion:"go1.9.3", Compiler:"gc", Platform:"linux/amd64"}
Server Versionが出力されるようになります。
# kubectl get nodes
NAME STATUS ROLES AGE VERSION
kube-master NotReady master 11m v1.10.0
まだflannelを入れていないため、STATUS
がNotReady
になります。
# kubectl get pods --all-namespaces -o wide
NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE
kube-system etcd-kube-master 0/1 Pending 0 4s <none> kube-master
kube-system kube-apiserver-kube-master 0/1 Pending 0 4s <none> kube-master
kube-system kube-controller-manager-kube-master 0/1 Pending 0 4s <none> kube-master
kube-system kube-dns-86f4d74b45-ccq57 0/3 Pending 0 5m <none> <none>
kube-system kube-proxy-tbrdc 1/1 NodeLost 0 5m 172.26.22.85 kube-master
kube-system kube-scheduler-kube-master 0/1 Pending 0 4s <none> kube-master
まだflannelを入れていないため、STATUS
がPending
になります。
flannel [Masterノードのみ]
deployする
# kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/v0.9.1/Documentation/kube-flannel.yml
clusterrole.rbac.authorization.k8s.io "flannel" created
clusterrolebinding.rbac.authorization.k8s.io "flannel" created
serviceaccount "flannel" created
configmap "kube-flannel-cfg" created
daemonset.extensions "kube-flannel-ds" created
確認
# kubectl get nodes
NAME STATUS ROLES AGE VERSION
kube-master Ready master 15m v1.10.0
STATUS
がNotReady
からReady
に変わります。
# kubectl get pods --all-namespaces -o wide
NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE
kube-system etcd-kube-master 1/1 Running 0 59s 172.26.22.85 kube-master
kube-system kube-apiserver-kube-master 1/1 Running 0 59s 172.26.22.85 kube-master
kube-system kube-controller-manager-kube-master 1/1 Running 0 59s 172.26.22.85 kube-master
kube-system kube-dns-86f4d74b45-ccq57 3/3 Running 0 6m 10.244.0.2 kube-master
kube-system kube-flannel-ds-79gcb 1/1 Running 0 1m 172.26.22.85 kube-master
kube-system kube-proxy-tbrdc 1/1 Running 0 6m 172.26.22.85 kube-master
kube-system kube-scheduler-kube-master 1/1 Running 0 58s 172.26.22.85 kube-master
STATUS
がNotReady
からRunning
に変わります。kube-dns-xxxxxがRunning
になるには、時間が掛かります。
Workerノードを追加する [Workerノードのみ]
ノードを追加する
kubeadm init
で出力されたコマンドを、そのままコピペして実行します。
# kubeadm join 172.26.22.85:6443 --token ddpdzf.s89pe0whxm0osqoc --discovery-token-ca-cert-hash sha256:ca6dcf315312663170f72cf081604b6635e7ad98bb3440656d43d6ed5cd34d0e
kubeconfig
# mkdir -p $HOME/.kube
# cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
# chown $(id -u):$(id -g) $HOME/.kube/config
もしくは、
# vi ~/.bash_profile
export KUBECONFIG=/etc/kubernetes/admin.conf
確認 [MasterとWorkerノード両方]
# kubectl get nodes
NAME STATUS ROLES AGE VERSION
kube-master Ready master 23m v1.10.0
kube-node1 Ready <none> 59s v1.10.0
WorkerノードもSTATUS
がReady
に変わります。(すぐには変わらない)
# kubectl get cs
NAME STATUS MESSAGE ERROR
scheduler Healthy ok
controller-manager Healthy ok
etcd-0 Healthy {"health": "true"}
Workerノードを削除するには?
Kubernetes自体のアンインストールは、次のコマンドで可能です。
|
Dashboard [Masterノードのみ]
インストール
# kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/master/src/deploy/recommended/kubernetes-dashboard.yaml
secret "kubernetes-dashboard-certs" created
serviceaccount "kubernetes-dashboard" created
role.rbac.authorization.k8s.io "kubernetes-dashboard-minimal" created
rolebinding.rbac.authorization.k8s.io "kubernetes-dashboard-minimal" created
deployment.apps "kubernetes-dashboard" created
service "kubernetes-dashboard" created
アクセスする
kube proxyを起動して、LISTENできるようにします。
# kubectl proxy
バインドアドレスがlocalhost
のみなので、SSHポート転送をしてアクセスします。TeraTermの場合は、MasterノードにSSHでログインした後、メニューの「設定」>「SSH転送...」から「追加」を押して次のように設定します。
これで、ローカルPCの8001ポートを、Masterノードを通してlocalhost(=Masterノード)の8001へ転送できるので、Masterノードから見ると、localhostから接続したように見えます。
ブラウザから次のアドレスでアクセスすると、Dashboardのトップページが見えるはずです。
http://localhost:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/
http://localhost:8001/ui は1.9で非推奨でしたが、1.10で廃止されました。
|
この段階では、まだDashboardにログインできません。
ポート転送なしでアクセスできるようにする
毎回ポート転送するのも面倒なので、ポート転送なしでもアクセスできるように、kube proxyを起動します。
# kubectl proxy --address=0.0.0.0 --accept-hosts='^.*$' &
--address
でバインドアドレスを指定しても、--accept-hosts
を付けないと <h3>Unauthorized</h3>
が出力されてしまいます。
権限を付与する
全機能を未認証で使用できるようにしておきます。適当なファイル名で、次の内容を保存します。
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: kubernetes-dashboard
labels:
k8s-app: kubernetes-dashboard
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: kubernetes-dashboard
namespace: kube-system
---
次のコマンドで適用します。
# kubectl apply -f (ファイル名)
これで「SKIP」を押すと、Dashboardの画面が見られるようになります。
Docker private repository [docker-repoのみ]
Kuberentesでは、Podをdeployするときdocker pull
でイメージを取得してからコンテナー化するため、private repositoryがあったほうが便利です。もちろんdocker.ioのprivate repositoryでも良いですが、この記事では自前のrepositoryを立ててみます。
インストール
# docker pull registry:2
起動
- 1回目
ストレージを永続化できるように起動します。
# docker run -d -p 5000:5000 -v /var/opt:/var/lib/registry registry:2
- 2回目以降
# docker start (コンテナー名)
コンテナー名は docker ps -a
で確認します。
確認
# netstat -anp | grep "LISTEN " | grep :5000
--insecure-registry
の設定も忘れずに。
まとめ
これで、Kubernetesで何かをする準備ができました。後編では実際にDockerイメージからKubernetesでサービスを公開してみたいと思います。
参考文献
-
マニュアル(clusterの作成)
マニュアルは英語ですが、一度は目を通しておいたほうが良いでしょう。 -
RedHat7上に構築
メモ書きレベルですが、UbuntuではなくRedHat7上で、かつKubernetes最新版の記述になっています。 -
flannel 0.90ではバグあり
私は最初から0.91なのでハマりませんでしたが、大きなバグがあるようです。 -
Kubernetesの本
O'ReillyからKubernetesの本の日本語訳がでました。内容は1.6ベースになっているようで、1.8や1.9の機能であるRoleやMulti Masterの記述はありませんでした。