2021/04/19
Ubuntu20.04のサーバーにkubeadmを使って開発用のk8sクラスターを作る
Ubuntu20.04のマシーンがオフィスにやってきました。せっかくなので、k8sクラスターをインストールして便利な開発用サービスを立てていこうと思います。
こちらの記事に従って構築しました。
事前準備
Swapをオフに設定
Swapがオフであること。kubeletが正常に動作するためにはswapは必ずオフでなければなりません。
$ sudo swapoff -a
iptablesがブリッジを通過するトラフィックを処理できるようにするか確認
# br_netfilterモジュールロード済を確認
$ lsmod | grep br_netfilter
br_netfilter 28672 0
bridge 192512 1 br_netfilter
$ cat /proc/sys/net/bridge/bridge-nf-call-iptables
1
# 1だったのでOK
iptablesがnftablesバックエンドを使用しないようになっているか確認
これは、少なくともDebian 10(Buster)、Ubuntu 19.04、Fedora 29、およびこれらのディストリビューションの新しいリリースでのデフォルトです。
Ubuntu 20.04は言及されていなかったので、大丈夫そうですが、以下で念の為確認
$ lsmod | grep nf_tables
# 見つからない
$ iptables --version
iptables v1.8.4 (legacy)
# 大丈夫みたい
kubeadm、kubelet、kubectlのインストール
kubeadmはkubeletやkubectlをインストールまたは管理しないため、kubeadmにインストールするKubernetesコントロールプレーンのバージョンと一致させる必要があります。
kubeadm / kubelet / kubectlはうまくバージョンを同期させておく必要がありそうです。
$ sudo apt-get update && sudo apt-get install -y apt-transport-https curl
$ curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
$ cat <<EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list
deb https://apt.kubernetes.io/ kubernetes-xenial main
EOF
$ sudo apt-get update
$ sudo apt-get install -y kubelet kubeadm kubectl
# パッケージが更新されないようにする。
$ sudo apt-mark hold kubelet kubeadm kubectl
kubelet は保留に設定されました。
kubeadm は保留に設定されました。
kubectl は保留に設定されました
コントロールプレーンノードのkubeletによって使用されるcgroupドライバーの設定の確認
Dockerを使用した場合、kubeadmは自動的にkubelet向けのcgroupドライバーを検出し、それを実行時に/var/lib/kubelet/kubeadm-flags.envファイルに設定します。
CRI(Container Runtime Interface)とは、2016年12月にKubernetes 1.5からαリリースされた、kubeletとコンテナランタイムが通信するためのI/Fを規定したもの
コンテナはdockerを利用しているので問題なさそうです。
kubeadm init
実行後に確認できました。
$ sudo cat /var/lib/kubelet/kubeadm-flags.env
KUBELET_KUBEADM_ARGS="--network-plugin=cni --pod-infra-container-image=k8s.gcr.io/pause:3.4.1"
コントロールプレーンノードの初期化
$ sudo kubeadm init --pod-network-cidr=192.168.0.0/16
kubectlをroot以外のユーザーでも実行できるようにする
$ mkdir -p $HOME/.kube
$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
$ sudo chown $(id -u):$(id -g) $HOME/.kube/config
# 以下で確認
$ kubectl get node
NAME STATUS ROLES AGE VERSION
<hostname> NotReady control-plane,master 89s v1.21.0
シングルマシンのクラスターでの設定
コントロールプレーンノードの隔離
デフォルトでは、セキュリティ上の理由により、クラスターはコントロールプレーンノードにPodをスケジューリングしません。たとえば、開発用のKubernetesシングルマシンのクラスターなどで、Podをコントロールプレーンノードにスケジューリングしたい場合は、次のコマンドを実行します。
$ kubectl taint nodes --all node-role.kubernetes.io/master-
node/<hostname> untainted
Podネットワークアドオンのインストール
備考: 現在、Calicoはkubeadmプロジェクトがe2eテストを実施している唯一のCNIプラグインです。 もしCNIプラグインに関する問題を見つけた場合、kubeadmやkubernetesではなく、そのCNIプラグインの課題管理システムへ問題を報告してください。
とりあえず、Calicoを使えば良いのかな?ということで
$ curl https://docs.projectcalico.org/manifests/calico.yaml -O
$ vim calico.yaml
calico.yaml
をそのままapplyしたら Couldn't autodetect an IPv4 address
というエラーが出てしまいました。
こちらは(通常は無線LANを使わないと思うのですが、現状LANポートが空いてなくて、無線で無理やりやっていたのでエラーになっていました。)
このコメントにある通りで、自分が今使っているNICを特定できるように IP_AUTODETECTION_METHOD
を変更(この時はwirelessのものを使っていたので、interface=wlo.*
を指定)することで解決できました。(地味に1時間程度ハマりました。)
containers:
# Runs calico-node container on each Kubernetes node. This
# container programs network policy and routes on each
# host.
- name: calico-node
image: docker.io/calico/node:v3.18.1
envFrom:
- configMapRef:
# Allow KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT to be overridden for eBPF mode.
name: kubernetes-services-endpoint
optional: true
env:
# ...中略...
- name: IP
value: "autodetect"
- name: IP_AUTODETECTION_METHOD
value: "interface=wlo.*"
$ kubectl apply -f calico.yaml
configmap/calico-config created
customresourcedefinition.apiextensions.k8s.io/bgpconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/bgppeers.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/blockaffinities.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/clusterinformations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/felixconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/globalnetworkpolicies.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/globalnetworksets.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/hostendpoints.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamblocks.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamconfigs.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamhandles.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ippools.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/kubecontrollersconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/networkpolicies.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/networksets.crd.projectcalico.org created
clusterrole.rbac.authorization.k8s.io/calico-kube-controllers created
clusterrolebinding.rbac.authorization.k8s.io/calico-kube-controllers created
clusterrole.rbac.authorization.k8s.io/calico-node created
clusterrolebinding.rbac.authorization.k8s.io/calico-node created
daemonset.apps/calico-node created
serviceaccount/calico-node created
deployment.apps/calico-kube-controllers created
serviceaccount/calico-kube-controllers created
Warning: policy/v1beta1 PodDisruptionBudget is deprecated in v1.21+, unavailable in v1.25+; use policy/v1 PodDisruptionBudget
poddisruptionbudget.policy/calico-kube-controllers created
NodeとPodの確認
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
<hostname> Ready control-plane,master 9m2s v1.21.0
$ kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
calico-kube-controllers-6d8ccdbf46-jwxgz 1/1 Running 0 23m
calico-node-bg896 1/1 Running 0 4m25s
coredns-558bd4d5db-jxpdc 1/1 Running 0 23m
coredns-558bd4d5db-m7dpb 1/1 Running 0 23m
etcd-<hostname> 1/1 Running 0 24m
kube-apiserver-<hostname> 1/1 Running 0 24m
kube-controller-manager-<hostname> 1/1 Running 0 24m
kube-proxy-v9wzk 1/1 Running 0 23m
kube-scheduler-<hostname> 1/1 Running 0 24m
無事必要なpodが起動しているのが確認できました。
nginxのpodのテスト
最後に、テストを兼ねて、nginxのプロセスを常駐させ、ちゃんとアクセスできるか確認してみました。
$ cat <<EOF > test_deployment.yaml
> apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
> kind: Deployment
> metadata:
> name: nginx-deployment
> spec:
> selector:
> matchLabels:
> app: nginx
> replicas: 2 # tells deployment to run 2 pods matching the template
> template:
> metadata:
> labels:
> app: nginx
> spec:
> containers:
> - name: nginx
> image: nginx:1.14.2
> ports:
> - containerPort: 80
> EOF
$ kubectl apply -f test_deployment.yaml
deployment.apps/nginx-deployment created
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-deployment-66b6c48dd5-8lflf 1/1 Running 0 22s
nginx-deployment-66b6c48dd5-xs4xr 1/1 Running 0 22s
$ kubectl port-forward nginx-deployment-66b6c48dd5-8lflf 8080:80
Forwarding from 127.0.0.1:8080 -> 80
Forwarding from [::1]:8080 -> 80
Handling connection for 8080
# 別のターミナルを立ち上げて、nginxに疎通できるか確認
$ curl localhost:8080
<!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>
<h1>Welcome to nginx!</h1>
<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>
以上で、ローカルのUbuntu20.04のサーバー(1台)にk8sを構築することができました。
現状ではシングル構成ですが、ヘビーユースするようになったら複数台構成でできるように拡張していきたいと思います。
関連する記事
[小〜中規模向け]GKEにTiDBをデプロイする
MySQL互換のNewSQLであるTiDBをGKEにデプロイしてみました。
NATS JetStream Controllerを使ってNATSをGKEにデプロイする
helm chartのnackを使って、NATS JetStreamサーバーをデプロイして、Stream/Consumerをk8sリソースとして管理する
GKEにDragonflydbをデプロイする
redis互換のdragonflydbをGKEにデプロイしました
[GKE]Kafka Strimziをアップグレードする
GKEにデプロイしているKafka Strimzi 0.26.0を0.30.0にアップグレードする