standalone-kubelet-with-containerd.md
가끔 kubernetes 같은건 너무 무거워서 단일 호스트에 docker만 띄워서 운영하는 경우같은걸 고민 하게 됩니다. 하지만 그냥 docker만 가지고 사용하면 컨테이너가 죽었을때 관리해 줘야 하는 불편함과 같이 기능을 보다 더 필요로 하게 됩니다. 그래서 이 방법을 소개해 드립니다.
이건 standalone kubelet 이라고 불리는 master 없이 node만 관리해주는 kubelet을 이용해서 container를 관리하는 방법입니다. 이건 k8s 초기 부터 원래 존재했던 컨셉이나 많이 알려져 있지 않아서 모르시는 분들이 많아서 이글을 작성해 봤습니다.
이 방법을 이용하면 실제 master 없이 kubelet 만으로 서비스를 할 수 있습니다. 컨테이너 자동 재시작, port forwarding, resource limit 등 기본적인 kubelet에서 제공하는 다양한 방법으로 컨테이너들을 관리 할 수 있습니다.
물론 이 방법은 기존에도 많이 소개되었기 때문에 1.20에 docker deprecated를 기념해서 containerd 버전으로 작성해 봤습니다. 미리 1.23에 containerd 사용을 체감할겸해서 재미로 보시면 좋겠습니다.
- demo
-
docker 버전 참고
-
cri-o 버전은 참고
containerd 설치
containerd를 위한 module 로드
cat <<EOF | sudo tee /etc/modules-load.d/containerd.conf
overlay
br_netfilter
EOF
모듈 로드
sudo modprobe overlay
sudo modprobe br_netfilter
필요한 sysctl 파라미터를 설정하면 재부팅 후에도 유지된다.
cat <<EOF | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF
재부팅하지 않고 sysctl 파라미터 적용
sudo sysctl --system
도커의 공식 GPG 키 추가
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
sudo apt-key --keyring /etc/apt/trusted.gpg.d/docker.gpg add -
도커 apt 리포지터리 추가
sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"
containerd 설치
sudo apt update && sudo apt install -y containerd.io
containerd 구성
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml
containerd 재시작
sudo systemctl restart containerd
kubelet 설치
kubernetes 공식 GPG 키 추가
curl -fsSL https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add
kubelet kubernetes-cni apt 리포지토리 추가
cat << EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list
deb https://apt.kubernetes.io/ kubernetes-xenial main
EOF
cni 설정
sudo mkdir -p /etc/cni/net.d
cat <<EOF | sudo tee /etc/cni/net.d/10-containerd-net.conflist
{
"cniVersion": "0.4.0",
"name": "containerd-net",
"plugins": [
{
"type": "bridge",
"bridge": "cni0",
"isGateway": true,
"ipMasq": true,
"promiscMode": true,
"ipam": {
"type": "host-local",
"ranges": [
[{
"subnet": "10.88.0.0/16"
}],
[{
"subnet": "2001:4860:4860::/64"
}]
],
"routes": [
{ "dst": "0.0.0.0/0" },
{ "dst": "::/0" }
]
}
},
{
"type": "portmap",
"capabilities": {"portMappings": true}
}
]
}
EOF
kubelet standalone 세팅
sudo mkdir -p /lib/systemd/system/kubelet.service.d
cat << "EOF" | sudo tee /lib/systemd/system/kubelet.service.d/10-standalone.conf
[Service]
ExecStart=
ExecStart=/usr/bin/kubelet --container-runtime=remote --container-runtime-endpoint=unix:///run/containerd/containerd.sock --pod-manifest-path=/etc/kubernetes/manifests
EOF
kubelet과 kubernetes-cni 설치
sudo apt update -y && sudo apt install -y kubelet kubernetes-cni
crictl client 설치
crictl 설치
VERSION="v1.19.0"
wget https://github.com/kubernetes-sigs/cri-tools/releases/download/$VERSION/crictl-$VERSION-linux-amd64.tar.gz
sudo tar zxvf crictl-$VERSION-linux-amd64.tar.gz -C /usr/local/bin
rm -f crictl-$VERSION-linux-amd64.tar.gz
client setting
cat << "EOF" | sudo tee /etc/crictl.yaml
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: false
EOF
test
test pod 생성
cat << EOF | sudo tee /etc/kubernetes/manifests/web.yaml
apiVersion: v1
kind: Pod
metadata:
name: static-web
spec:
containers:
- name: web
image: nginx
ports:
- name: web
containerPort: 80
hostPort: 8080
protocol: TCP
EOF
local pod ip로 테스트 (위의 containerport)
PODID=$(sudo crictl pods | awk /static-web/{'print $1'})
PODIP=$(sudo crictl inspectp -o go-template --template '{{.status.network.ip}}' ${PODID})
curl $PODIP:80
외부에서도 접근 가능한 ip로 테스트 (위의 hostport)
ROUTABLE_NODE_IP=$(ip -o r g 1 | awk '{print $7}')
curl $ROUTABLE_NODE_IP:8080