LoginSignup
23
21

More than 5 years have passed since last update.

Amazon EC2でCentOSにKubernetesを構築する(前編)

Last updated at Posted at 2018-05-29

はじめに

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
:information_source: HTTPプロキシーを設定するには?

Service Unitファイルに環境変数を追加します。NO_PROXYにはprivate repositoryのIPアドレスを加えておきます。
※注1 NO_PROXY にはCIDR記法で書けない
※注2 複数ある場合はカンマ区切り。

# mkdir -p /etc/systemd/system/docker.service.d/
# vi /etc/systemd/system/docker.service.d/http-proxy.conf
Environment="HTTP_PROXY=http://(ユーザー名):(パスワード)@(プロキシーのサーバー名)" "HTTPS_PROXY=http://(ユーザー名):(パスワード)@(プロキシーのサーバー名)"
Environment="NO_PROXY=127.0.0.1,172.26.22.6"

確認する

# 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
:information_source: HTTPプロキシーを設定するには?

/etc/yum.conf に追加します。

proxy=http://(プロキシーのサーバー名)
proxy_username=(ユーザー名)
proxy_password=(パスワード)

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ノードのアドレスを指定します。

:information_source: HTTPプロキシーを設定するには?

kubeadm initでは外に接続するため、環境変数http_proxy, https_proxy, no_proxy入れておきます。
※注1 環境変数名は小文字。CIDR記法で書ける。
※注2 private networkのIPアドレスも入れておくこと!

# export http_proxy=http://(ユーザー名):(パスワード)@(プロキシーのサーバー名)
# export no_proxy=172.26.22.0/24,localhost,127.0.0.1,10.96.0.0/12,10.244.0.0/16

標準出力で出る最後の行は、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
:information_source: トークンの有効期限と再発行は?

トークンの有効期限は24時間です。有効期限が切れた場合は、再発行できます。

# kubeadm token list
# kubeadm token create --print-join-command

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を入れていないため、STATUSNotReadyになります。

# 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を入れていないため、STATUSPendingになります。

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

STATUSNotReadyから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

STATUSNotReadyから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ノードもSTATUSReadyに変わります。(すぐには変わらない)

# kubectl get cs
NAME                 STATUS    MESSAGE              ERROR
scheduler            Healthy   ok
controller-manager   Healthy   ok
etcd-0               Healthy   {"health": "true"}
:information_source: Workerノードを削除するには?


# kubectl drain (node name) --delete-local-data --force --ignore-daemonsets
# kubectl delete node (node name)
Kubernetes自体のアンインストールは、次のコマンドで可能です。

# kubeadm reset

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転送...」から「追加」を押して次のように設定します。

2018-05-01_115006.png

これで、ローカルPCの8001ポートを、Masterノードを通してlocalhost(=Masterノード)の8001へ転送できるので、Masterノードから見ると、localhostから接続したように見えます。

ブラウザから次のアドレスでアクセスすると、Dashboardのトップページが見えるはずです。

http://localhost:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/
:information_source: http://localhost:8001/ui は1.9で非推奨でしたが、1.10で廃止されました。

2018-05-01_115516.png

この段階では、まだ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の記述はありませんでした。

23
21
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
23
21