はじめに
この記事で扱うこと
- kubeadmを使ってKubernetesクラスタを構築する
- シングルノードクラスタとする(マスターノードにデプロイ)
- AWSのEC2インスタンスを利用する
1. ec2インスタンスの起動
マシンの要件としては、下記の通りkubeadmのインストールに記載があります。
今回はCentOSを選択します。
始める前に
- 次のいずれかが動作しているマシンが必要です
- Ubuntu 16.04+
- Debian 9+
- CentOS 7
- Red Hat Enterprise Linux (RHEL) 7
- Fedora 25+
- HypriotOS v1.0.1+
- Container Linux (tested with 1800.6.0)
- 1台あたり2GB以上のメモリ(2GBの場合、アプリ用のスペースはほとんどありません)
- 2コア以上のCPU
- クラスター内のすべてのマシン間で通信可能なネットワーク(パブリックネットワークでもプライベートネットワークでも構いません)
- ユニークなhostname、MACアドレス、とproduct_uuidが各ノードに必要です。詳細はここを参照してください。
- マシン内の特定のポートが開いていること。詳細はここを参照してください。
- Swapがオフであること。kubeletが正常に動作するためにはswapは必ずオフでなければなりません。
EC2インスタンスの構成は下記の通りとします。
2GB以上のメモリ、2コア以上のCPUを満たすようt3.small
のインスタンスを選択しています。
(※ t2.microでも動いたよという記事もちらほら見かけるのちょっと触るくらいならt2.microでも問題なさそうな気がします。)
項目 | 設定 |
---|---|
AMI | CentOS 7 (x86_64) - with Updates HVM |
アーキテクチャ | x86_64 |
インスタンスタイプ | t3.small (2 vCPU / 2 GiBメモリ) |
EBS ボリューム | 8 GB |
公開するポートについても、kubeadmのインストールに下記のように記載があります。
今回はMasterノード1つだけのシングルノードクラスタなので、NodePortで使用する30000-32767
の通信のみ許可します。
セキュリティグループのインバウンドルールはこのように設定しています。
(複数ノードでクラスタを構築したい方は上記の画像の通りにポートを解放します。)
以上の設定でEC2インスタンスを起動し、sshでログインします。
CentOSのユーザはcentos
です。(ec2-userではありません。)
[centos@ip-172-31-7-118 ~]$
2. クラスタセットアップの前準備
はじめにrootユーザに昇格しておきます。
[centos@ip-172-31-7-118 ~]$ sudo su -
[root@ip-172-31-7-118 ~]#
次にkubeadmのインストールに記載のネットワーク要件を満たすように設定を行います。
Linuxノードのiptablesがブリッジを通過するトラフィックを正確に処理する要件として、net.bridge.bridge-nf-call-iptablesをsysctlの設定ファイルで1に設定してください。
[root@ip-172-31-7-118 ~]# modprobe br_netfilter
[root@ip-172-31-7-118 ~]# lsmod | grep br_netfilter
br_netfilter 22256 0
bridge 151336 1 br_netfilter
[root@ip-172-31-7-118 ~]# cat <<EOF > /etc/sysctl.d/k8s.conf
> net.bridge.bridge-nf-call-ip6tables = 1
> net.bridge.bridge-nf-call-iptables = 1
> EOF
下記コマンドで設定が反映されていることを確認します(下の方が優先される)。
[root@ip-172-31-7-118 ~]# sysctl --system | grep net.bridge.bridge-nf-call
net.bridge.bridge-nf-call-ip6tables = 0
net.bridge.bridge-nf-call-iptables = 0
net.bridge.bridge-nf-call-arptables = 0
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
次にSwap領域が無効になっていることを確認します。
[root@ip-172-31-7-118 ~]# swapon -s
[root@ip-172-31-7-118 ~]#
何も表示されていないのでSwap領域は無効になっているようです。
Swap領域が有効になっている場合は下記コマンドで無効化します。
[root@ip-172-31-7-118 ~]# swapoff -a
以上で前準備が完了となります。
3. コンテナランタイムのインストール
CRIのインストールに従ってコンテナランタイムのインストールを行います。
ほとんどコマンドのコピペ作業になります。
[root@ip-172-31-7-118 ~]# yum install -y yum-utils device-mapper-persistent-data lvm2
[root@ip-172-31-7-118 ~]# yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
ランタイムとしてはcontainerd
を利用しています。
注意点としては下手に最新バージョンを利用したりするとkubernetesが起動しなくなるため、バージョンも公式サイトの手順にあるものをそのまま利用します。
[root@ip-172-31-7-118 ~]# yum update -y && yum install -y \
> containerd.io-1.2.13 \
> docker-ce-19.03.11 \
> docker-ce-cli-19.03.11
インストールに成功するとdockerデーモンが読み込まれていることが確認できます。
[root@ip-172-31-7-118 ~]# systemctl status docker
● docker.service - Docker Application Container Engine
Loaded: loaded (/usr/lib/systemd/system/docker.service; disabled; vendor preset: disabled)
Active: inactive (dead)
Docs: https://docs.docker.com
/usr/lib/systemd/system/docker.service
の中身を確認すると
--containerd=/run/containerd/containerd.sock
とランタイムにcontainerdのソケットファイルが設定されていることが分かります。
[root@ip-172-31-7-118 ~]# cat /usr/lib/systemd/system/docker.service
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
BindsTo=containerd.service
After=network-online.target firewalld.service containerd.service
Wants=network-online.target
Requires=docker.socket
[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutSec=0
RestartSec=2
Restart=always
~~~ 以下略 ~~~
[root ~]# mkdir /etc/docker
[root@ip-172-31-7-118 ~]# cat > /etc/docker/daemon.json <<EOF
> {
> "exec-opts": ["native.cgroupdriver=systemd"],
> "log-driver": "json-file",
> "log-opts": {
> "max-size": "100m"
> },
> "storage-driver": "overlay2",
> "storage-opts": [
> "overlay2.override_kernel_check=true"
> ]
> }
> EOF
[root@ip-172-31-7-118 ~]# mkdir -p /etc/systemd/system/docker.service.d
dockerデーモンの設定を再読み込みし、サービスを起動します。
[root@ip-172-31-7-118 ~]# systemctl daemon-reload
[root@ip-172-31-7-118 ~]# systemctl enable --now docker
Created symlink from /etc/systemd/system/multi-user.target.wants/docker.service to /usr/lib/systemd/system/docker.service.
dockerのサービスが起動していることを確認します。
Active: active (running)
とあれば問題なく起動されています。
[root@ip-172-31-7-118 ~]# systemctl status docker
● docker.service - Docker Application Container Engine
Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
Active: active (running) since Sun 2021-08-08 13:39:09 UTC; 5s ago
Docs: https://docs.docker.com
Main PID: 28157 (dockerd)
Tasks: 10
Memory: 37.8M
CGroup: /system.slice/docker.service
└─28157 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
4. kubeadm、kubelet、kubectlのインストール
kubeadmのインストールに従ってkubeadm、kubelet、kubectlをインストールします。
こちらもほとんどコマンドのコピペ作業になります。
初めにyumレポジトリの登録をします。
[root@ip-172-31-7-118 ~]# cat <<EOF > /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
> EOF
[root@ip-172-31-7-118 ~]# setenforce 0
[root@ip-172-31-7-118 ~]# sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
kubeadm、kubelet、kubectlのパッケージをインストールします。
[root@ip-172-31-7-118 ~]# yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes
インストールが完了したらkubeletのサービスが読み込まれていることを確認します。
[root@ip-172-31-7-118 ~]# systemctl status kubelet
● kubelet.service - kubelet: The Kubernetes Node Agent
Loaded: loaded (/usr/lib/systemd/system/kubelet.service; disabled; vendor preset: disabled)
Drop-In: /usr/lib/systemd/system/kubelet.service.d
└─10-kubeadm.conf
Active: inactive (dead)
Docs: https://kubernetes.io/docs/
kubeletのサービスを起動します。
[root@ip-172-31-7-118 ~]# systemctl enable --now kubelet
Created symlink from /etc/systemd/system/multi-user.target.wants/kubelet.service to /usr/lib/systemd/system/kubelet.service.
ステータスを確認すると失敗しているようですが、気にせず次の章(kubeadmでクラスタの初期化)へ移ります。
[root@ip-172-31-7-118 ~]# systemctl status kubelet
● kubelet.service - kubelet: The Kubernetes Node Agent
Loaded: loaded (/usr/lib/systemd/system/kubelet.service; enabled; vendor preset: disabled)
Drop-In: /usr/lib/systemd/system/kubelet.service.d
└─10-kubeadm.conf
Active: activating (auto-restart) (Result: exit-code) since Sun 2021-08-08 14:00:15 UTC; 1s ago
Docs: https://kubernetes.io/docs/
Process: 4988 ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS (code=exited, status=1/FAILURE)
Main PID: 4988 (code=exited, status=1/FAILURE)
Aug 08 14:00:14 ip-172-31-7-118.us-west-2.compute.internal systemd[1]: Unit kubelet.service entered failed state.
Aug 08 14:00:15 ip-172-31-7-118.us-west-2.compute.internal systemd[1]: kubelet.service failed.
5. kubeadmでクラスタの初期化
クラスタの初期化を行う前に一般ユーザとして利用したいので、root
からcentos
へ切り替えます。
[root@ip-172-31-7-118 ~]# exit
logout
[centos@ip-172-31-7-118 ~]$
kubeadmコマンドでクラスタの初期化を行います。
kubeadmを使用したクラスターの作成に説明があります。
ネットワークアドオンとしてflannelを利用するため(後述)ここでは--pod-network-cidr=10.244.0.0/16
をオプションに設定しています。
[centos@ip-172-31-7-118 ~]$ sudo kubeadm init --apiserver-advertise-address $(hostname -i) --pod-network-cidr=10.244.0.0/16
~~~中略~~~
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
Alternatively, if you are the root user, you can run:
export KUBECONFIG=/etc/kubernetes/admin.conf
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 172.31.7.118:6443 --token 539hwl.b1...........ak \
--discovery-token-ca-cert-hash sha256:db513........................................2deb
クラスタの初期化が完了しました。
今回は一般ユーザで利用しているため、
To start using your cluster, you need to run the following as a regular user:
と記載されている手順を実施します。
[centos@ip-172-31-7-118 ~]$ mkdir -p $HOME/.kube
[centos@ip-172-31-7-118 ~]$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
[centos@ip-172-31-7-118 ~]$ sudo chown $(id -u):$(id -g) $HOME/.kube/config
複数ノードでクラスタを構築している方は、
Then you can join any number of worker nodes by running the following on each as root:
に記載の通り、下記のコマンドをクラスタへ参加させたいノード上で実行することによりKubernetesクラスタへ参加させることができます。
今回はシングルノードクラスタなのでこの手順は実施しません。
kubeadm join 172.31.7.118:6443 --token 539hwl.b1...........ak \
--discovery-token-ca-cert-hash sha256:db513........................................2deb
この時点で先ほど失敗していたkubelet
のサービスが起動していることが確認できます。
[centos@ip-172-31-7-118 ~]$ systemctl status kubelet
● kubelet.service - kubelet: The Kubernetes Node Agent
Loaded: loaded (/usr/lib/systemd/system/kubelet.service; enabled; vendor preset: disabled)
Drop-In: /usr/lib/systemd/system/kubelet.service.d
└─10-kubeadm.conf
Active: active (running) since Sun 2021-08-08 14:04:31 UTC; 7min ago
Docs: https://kubernetes.io/docs/
Main PID: 6595 (kubelet)
Tasks: 13
Memory: 98.4M
CGroup: /system.slice/kubelet.service
└─6595 /usr/bin/kubelet --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf --config=/var/lib/kubelet/config.yaml --network-plugin=cni -...
また、kubectl
コマンドでノード一覧を取得することもできます。
この時点ではまだNotReady
になっています。
[centos@ip-172-31-7-118 ~]$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
ip-172-31-7-118.us-west-2.compute.internal NotReady control-plane,master 8m54s v1.22.0
kubeadm init
で何か問題が発生したり、オプションの設定を修正したいときはkubeadm reset
コマンドでリセットすることができます。
[centos@ip-172-31-7-118 ~]$ kubeadm reset
kubeadmを使用したクラスターの作成にも記載がありますが、デフォルトではMasterノードにPodをスケジュールすることはできません。
そのため、下記のコマンドでMasterノードにもPodをスケジュールできるようにします。
[centos@ip-172-31-7-118 ~]$ kubectl taint nodes --all node-role.kubernetes.io/master-
node/ip-172-31-7-118.us-west-2.compute.internal untainted
6. ネットワークアドオンの設定
ここではネットワークアドオンとしてflannel
を利用します。
https://github.com/flannel-io/flannelに記載の通り、下記コマンドでインストールを行います。
[centos@ip-172-31-7-118 ~]$ kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
Warning: policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
podsecuritypolicy.policy/psp.flannel.unprivileged created
clusterrole.rbac.authorization.k8s.io/flannel created
clusterrolebinding.rbac.authorization.k8s.io/flannel created
serviceaccount/flannel created
configmap/kube-flannel-cfg created
daemonset.apps/kube-flannel-ds created
この時点でMasterノードがReady
になり、セットアップがすべて完了しました。
[centos@ip-172-31-7-118 ~]$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
ip-172-31-7-118.us-west-2.compute.internal Ready control-plane,master 24m v1.22.0
7. Nginxで動作確認
最後にNginxで動作確認を行います。
下記のファイルを作成します。
外部からアクセスできるようにServiceにNodePort 30000番を設定して公開しています。
apiVersion: v1
kind: Pod
metadata:
name: mypod
labels:
app: mynginx
spec:
containers:
- name: mynginx
image: nginx:1.19.8-alpine
---
apiVersion: v1
kind: Service
metadata:
name: myservice
spec:
ports:
- name: http
port: 80
protocol: TCP
targetPort: 80
nodePort: 30000
selector:
app: mynginx
type: NodePort
kubectl apply
してブラウザからアクセスしてみます。
[centos@ip-172-31-7-118 ~]$ kubectl apply -f Pod.yaml
pod/mypod created
service/myservice created
[centos@ip-172-31-7-118 ~]$ kubectl get pods,service
NAME READY STATUS RESTARTS AGE
pod/mypod 1/1 Running 0 76s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 31m
service/myservice NodePort 10.108.194.192 <none> 80:30000/TCP 76s
参考資料
kubeadmのインストール
CRIのインストール
kubeadmを使用したクラスターの作成
[https://github.com/flannel-io/flannel](https://github.com/flannel-io/flannel