Skip to content

Instantly share code, notes, and snippets.

@leoh0
Last active September 15, 2022 00:43
Show Gist options
  • Save leoh0/2129aeff1e4ee1456d95011d402d6e1f to your computer and use it in GitHub Desktop.
Save leoh0/2129aeff1e4ee1456d95011d402d6e1f to your computer and use it in GitHub Desktop.
containerd를 이용해서 standalone kubelet 사용하기

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

asciicast

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
# standalone-kubelet-with-containerd.md
# docker 버전
# https://github.com/kelseyhightower/standalone-kubelet-tutorial/blob/master/README.md
# cri-o 버전은 아래를 참고하세요.
# https://gist.github.com/dmesser/ffa556788660a7d23999427be4797d38
## 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})
#### 로컬에서만 접근 가능한 해당 pod의 ip와 포트로 접근 한다.
curl $PODIP:80
#### 외부에서도 접근 가능한 ip로 테스트 (위의 hostport)
ROUTABLE_NODE_IP=$(ip -o r g 1 | awk '{print $7}')
#### 외부에서도 접근 가능한 해당 pod의 ip와 외부 포트로 접근 한다.
curl $ROUTABLE_NODE_IP:8080
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment