オンプレミスな環境にkubernetesを構築
environment
- ubuntu22.04
- kubernetes
- version 1.28.2
- control node * 1
- worker node * 2
VMなので1台作り、kubernetes環境が初期状態で複製しました。
install kubernetes
https://kubernetes.io/ja/docs/setup/production-environment/tools/kubeadm/install-kubeadm/
sudo apt-get install -y apt-transport-https ca-certificates curl gpg
curl -fsSL https://dl.k8s.io/apt/doc/apt-key.gpg | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-archive-keyring.gpg
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl
whereis kubectl
install docker
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"
apt-get update && apt-get install -y containerd.io docker-ce docker-ce-cli
systemctl list-unit-files|grep -i docker
cat /etc/docker/daemon.json
cat > /etc/docker/daemon.json <<EOF
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2"
}
EOF
mkdir -p /etc/systemd/system/docker.service.d
systemctl daemon-reload
systemctl restart docker
docker ps
set iptables
sudo apt-get install -y iptables arptables ebtables
update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy
update-alternatives --set arptables /usr/sbin/arptables-legacy
update-alternatives --set ebtables /usr/sbin/ebtables-legacy
systemctl daemon-reload
systemctl restart kubelet
kubectl get nodes
cat <<EOF > /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
swapon -s
swapoff /swap.img
vi /etc/fstab
control planeでinit
root@k8s-cont01:/home/ocarina# kubeadm init --control-plane-endpoint 172.31.1.1:6443 --pod-network-cidr=10.255.0.0/16 --upload-certs
I0212 22:10:29.072594 1973 version.go:256] remote version is much newer: v1.29.1; falling back to: stable-1.28
[init] Using Kubernetes version: v1.28.6
[preflight] Running pre-flight checks
[preflight] Pulling images required for setting up a Kubernetes cluster
[preflight] This might take a minute or two, depending on the speed of your internet connection
[preflight] You can also perform this action in beforehand using 'kubeadm config images pull'
[certs] Using certificateDir folder "/etc/kubernetes/pki"
[certs] Generating "ca" certificate and key
[certs] Generating "apiserver" certificate and key
[certs] apiserver serving cert is signed for DNS names [k8s-cont01 kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] and IPs [10.96.0.1 172.31.1.1]
[certs] Generating "apiserver-kubelet-client" certificate and key
[certs] Generating "front-proxy-ca" certificate and key
[certs] Generating "front-proxy-client" certificate and key
[certs] Generating "etcd/ca" certificate and key
[certs] Generating "etcd/server" certificate and key
[certs] etcd/server serving cert is signed for DNS names [k8s-cont01 localhost] and IPs [172.31.1.1 127.0.0.1 ::1]
[certs] Generating "etcd/peer" certificate and key
[certs] etcd/peer serving cert is signed for DNS names [k8s-cont01 localhost] and IPs [172.31.1.1 127.0.0.1 ::1]
[certs] Generating "etcd/healthcheck-client" certificate and key
[certs] Generating "apiserver-etcd-client" certificate and key
[certs] Generating "sa" key and public key
[kubeconfig] Using kubeconfig folder "/etc/kubernetes"
[kubeconfig] Writing "admin.conf" kubeconfig file
[kubeconfig] Writing "kubelet.conf" kubeconfig file
[kubeconfig] Writing "controller-manager.conf" kubeconfig file
[kubeconfig] Writing "scheduler.conf" kubeconfig file
[etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests"
[control-plane] Using manifest folder "/etc/kubernetes/manifests"
[control-plane] Creating static Pod manifest for "kube-apiserver"
[control-plane] Creating static Pod manifest for "kube-controller-manager"
[control-plane] Creating static Pod manifest for "kube-scheduler"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Starting the kubelet
[wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory "/etc/kubernetes/manifests". This can take up to 4m0s
[kubelet-check] Initial timeout of 40s passed.
[apiclient] All control plane components are healthy after 74.022769 seconds
[upload-config] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
[kubelet] Creating a ConfigMap "kubelet-config" in namespace kube-system with the configuration for the kubelets in the cluster
[upload-certs] Storing the certificates in Secret "kubeadm-certs" in the "kube-system" Namespace
[upload-certs] Using certificate key:
0febb335b6d9438814b8ae24673af74811c9dc7fa4ebae5d202689071594ea7f
[mark-control-plane] Marking the node k8s-cont01 as control-plane by adding the labels: [node-role.kubernetes.io/control-plane node.kubernetes.io/exclude-from-external-load-balancers]
[mark-control-plane] Marking the node k8s-cont01 as control-plane by adding the taints [node-role.kubernetes.io/control-plane:NoSchedule]
[bootstrap-token] Using token: exonyk.7rrbqyzc533da4ft
[bootstrap-token] Configuring bootstrap tokens, cluster-info ConfigMap, RBAC Roles
[bootstrap-token] Configured RBAC rules to allow Node Bootstrap tokens to get nodes
[bootstrap-token] Configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials
[bootstrap-token] Configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token
[bootstrap-token] Configured RBAC rules to allow certificate rotation for all node client certificates in the cluster
[bootstrap-token] Creating the "cluster-info" ConfigMap in the "kube-public" namespace
[kubelet-finalize] Updating "/etc/kubernetes/kubelet.conf" to point to a rotatable kubelet client certificate and key
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy
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/
You can now join any number of the control-plane node running the following command on each as root:
kubeadm join 172.31.1.1:6443 --token exonyk.7rrbqyzc533da4ft \
--discovery-token-ca-cert-hash sha256:4e8085fde3a129befbdbba029da2695aaf935203adcde36b5c708dc22266adee \
--control-plane --certificate-key 0febb335b6d9438814b8ae24673af74811c9dc7fa4ebae5d202689071594ea7f
Please note that the certificate-key gives access to cluster sensitive data, keep it secret!
As a safeguard, uploaded-certs will be deleted in two hours; If necessary, you can use
"kubeadm init phase upload-certs --upload-certs" to reload certs afterward.
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join 172.31.1.1:6443 --token exonyk.7rrbqyzc533da4ft \
--discovery-token-ca-cert-hash sha256:4e8085fde3a129befbdbba029da2695aaf935203adcde36b5c708dc22266adee
errorの場合
reset
systemctl stop kubelet
yes | kubeadm reset
iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X && ipvsadm -C
systemctl restart containerd
error回避
https://github.com/kubernetes/kubeadm/issues/2699#issuecomment-1353250314
systemctl stop kubelet
\rm /etc/containerd/config.toml
containerd config default | sudo tee /etc/containerd/config.toml
sed -ie 's/SystemdCgroup = false/SystemdCgroup = true/g' /etc/containerd/config.toml
PAUSE_IMAGE=$(kubeadm config images list | grep pause 2>/dev/null)
echo $PAUSE_IMAGE
sudo -E sed -i "s,sandbox_image = .*,sandbox_image = \"$PAUSE_IMAGE\",g" /etc/containerd/config.toml
systemctl restart containerd
もう一度init
workerのjoin
root@k8s-worker02:/home/ocarina# kubeadm join 172.31.1.1:6443 --token exonyk.7rrbqyzc533da4ft \
--discovery-token-ca-cert-hash sha256:4e8085fde3a129befbdbba029da2695aaf935203adcde36b5c708dc22266adee
configファイルコピー
control1からコピー
scp /etc/kubernetes/admin.conf 172.31.1.2:/etc/kubernetes/.
scp /etc/kubernetes/admin.conf 172.31.1.3:/etc/kubernetes/.
worker1,2 一般ユーザーで
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
CNI
https://docs.cilium.io/en/stable/gettingstarted/k8s-install-default/
download
CILIUM_CLI_VERSION=$(curl -s https://raw.githubusercontent.com/cilium/cilium-cli/main/stable.txt)
CLI_ARCH=amd64
if [ "$(uname -m)" = "aarch64" ]; then CLI_ARCH=arm64; fi
curl -L --fail --remote-name-all https://github.com/cilium/cilium-cli/releases/download/${CILIUM_CLI_VERSION}/cilium-linux-${CLI_ARCH}.tar.gz{,.sha256sum}
sha256sum --check cilium-linux-${CLI_ARCH}.tar.gz.sha256sum
sudo tar xzvfC cilium-linux-${CLI_ARCH}.tar.gz /usr/local/bin
rm cilium-linux-${CLI_ARCH}.tar.gz{,.sha256sum}
install
root@k8s-cont01:/home/ocarina# cilium install
ℹ️ Using Cilium version 1.14.6
🔮 Auto-detected cluster name: kubernetes
🔮 Auto-detected kube-proxy has been installed
root@k8s-cont01:/home/ocarina# cilium status
/¯¯\
/¯¯\__/¯¯\ Cilium: 1 errors, 3 warnings
\__/¯¯\__/ Operator: 1 errors, 1 warnings
/¯¯\__/¯¯\ Envoy DaemonSet: disabled (using embedded mode)
\__/¯¯\__/ Hubble Relay: disabled
\__/ ClusterMesh: disabled
Deployment cilium-operator Desired: 1, Unavailable: 1/1
DaemonSet cilium Desired: 3, Unavailable: 3/3
Containers: cilium Pending: 3
cilium-operator Pending: 1
Cluster Pods: 0/0 managed by Cilium
Helm chart version: 1.14.6
Image versions cilium quay.io/cilium/cilium:v1.14.6@sha256:37a49f1abb333279a9b802ee8a21c61cde9dd9138b5ac55f77bdfca733ba852a: 3
cilium-operator quay.io/cilium/operator-generic:v1.14.6@sha256:2f0bf8fb8362c7379f3bf95036b90ad5b67378ed05cd8eb0410c1afc13423848: 1
Errors: cilium cilium 3 pods of DaemonSet cilium are not ready
cilium-operator cilium-operator 1 pods of Deployment cilium-operator are not ready
Warnings: cilium cilium-4cfqh pod is pending
cilium cilium-9vxxz pod is pending
cilium cilium-hhq8z pod is pending
cilium-operator cilium-operator-c8cfd6fcf-v5hdh pod is pending
status check failed
しばらく待つ....
bashroot@k8s-cont01:/home/ocarina# cilium status
/¯¯\
/¯¯\__/¯¯\ Cilium: OK
\__/¯¯\__/ Operator: OK
/¯¯\__/¯¯\ Envoy DaemonSet: disabled (using embedded mode)
\__/¯¯\__/ Hubble Relay: disabled
\__/ ClusterMesh: disabled
Deployment cilium-operator Desired: 1, Ready: 1/1, Available: 1/1
DaemonSet cilium Desired: 3, Ready: 3/3, Available: 3/3
Containers: cilium Running: 3
cilium-operator Running: 1
Cluster Pods: 2/2 managed by Cilium
Helm chart version: 1.14.6
Image versions cilium quay.io/cilium/cilium:v1.14.6@sha256:37a49f1abb333279a9b802ee8a21c61cde9dd9138b5ac55f77bdfca733ba852a: 3
cilium-operator quay.io/cilium/operator-generic:v1.14.6@sha256:2f0bf8fb8362c7379f3bf95036b90ad5b67378ed05cd8eb0410c1afc13423848: 1
root@k8s-cont01:/home/ocarina#
root@k8s-cont01:/home/ocarina# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-cont01 Ready control-plane 77m v1.28.2
k8s-worker02 Ready <none> 23m v1.28.2
k8s-worker03 Ready <none> 23m v1.28.2
root@k8s-cont01:/home/ocarina# kubectl get pods -n kube-system | grep cilium
cilium-cp6vw 1/1 Running 0 13m
cilium-fq9qx 1/1 Running 0 13m
cilium-nxt5h 1/1 Running 0 13m
cilium-operator-c8cfd6fcf-pl59q 1/1 Running 6 (3m31s ago) 13m
root@k8s-cont01:/home/ocarina#
test
create pod
ocarina@k8s-worker03:~$ kubectl create deployment nginx --image=nginx:latest
deployment.apps/nginx created
ocarina@k8s-worker03:~$ kubectl expose deployment nginx --type=NodePort --port=80
service/nginx exposed
ocarina@k8s-worker03:~$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 25h
nginx NodePort 10.104.210.75 <none> 80:30288/TCP 8s
network
node
root@k8s-cont01:/home/ocarina# iptables -nvL -t nat | grep 302
0 0 KUBE-EXT-2CMXP7HKUVJN7L6M tcp -- * * 0.0.0.0/0 0.0.0.0/0 /* default/nginx */ tcp dpt:30288
コントロールプレーンノード含め全台で同一のnat設定が作られたことを確認した。
ip_forwardは自動で有効になっていた。
root@k8s-cont01:/home/ocarina# grep ip_forward /etc/sysctl.conf
#net.ipv4.ip_forward=1
root@k8s-cont01:/home/ocarina# sysctl -a | grep ip_forward\
net.ipv4.ip_forward = 1
grepした限り、kube-proxyかciliumで自動的に有効にしてるっぽい。
router側でnat
iptables -t nat -A PREROUTING -d 172.31.0.200 -p tcp -m tcp --dport 30288 -j DNAT --to-destination 172.31.1.254
vip
worker nodeにてkeepalivedでvrrp 172.31.1.254 をlistenするように設定
ネットワークの外からの接続確認
ocarina@ab350-pro4:~$ curl --head http://172.31.0.200:30288/
HTTP/1.1 200 OK
Server: nginx/1.25.3
Date: Tue, 13 Feb 2024 14:28:24 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Tue, 24 Oct 2023 13:46:47 GMT
Connection: keep-alive
ETag: "6537cac7-267"
Accept-Ranges: bytes