1. Docker 설치
위 블로그 따라서 Docker를 먼저 설치한다.
설치가 끝났다면 docker ps 명령어를 입력해 보자.
위와 같은 에러가 날 수 있다.
해당 문제는 사용자가 /var/run/docker.sock 에 접근하려고 했지만 권한이 없어 발생하는 문제로, 사용자가 root:docker 권한을 가지고 있어야 한다.
root 권한을 가지고 실행하는 것은 권장되지 않으므로, 사용자를 docker group에 포함시켜주면 된다.
($USER 환경 변수는 현재 로그인한 사용자 아이디를 나타내므로 그대로 입력하면 된다.)
sudo usermod -a -G docker $USER
서버를 reboot 한 후 id를 입력해보자
현재 사용자의 그룹에 docker가 포함되었다. 이제 docker ps 등의 명령어를 사용할 수 있다.
2. kubeadm 설치
- apt 패키지 색인을 업데이트하고, 쿠버네티스 apt 리포지터리를 사용하는 데 필요한 패키지를 설치한다.
-
sudo apt-get update sudo apt-get install -y apt-transport-https ca-certificates curl
- 구글 클라우드의 공개 사이닝 키를 다운로드 한다.
-
sudo curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
- 쿠버네티스 apt 리포지터리를 추가한다.
-
echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
- apt 패키지 색인을 업데이트하고, kubelet, kubeadm, kubectl을 설치하고 해당 버전을 고정한다.
-
sudo apt-get update && sudo apt-get install -y kubelet kubeadm kubectl && sudo apt-mark hold kubelet kubeadm kubectl
경고:
컨테이너 런타임과 kubelet의 cgroup 드라이버를 일치시켜야 하며, 그렇지 않으면 kubelet 프로세스에 오류가 발생한다.
3. cgroup 드라이버 구성
개념
cgroup이란?
cgroup은 control group의 준말로 컨테이너 생성에 있어서 기초되는 개념이다.
컨테이너가 생성될 때 저수준 런타임 단계에서 linux kernel의 namespace와 cgroup을 이용해서 컨테이너를 만들고 실행시킨다.
컨테이너라는 격리된 공간에서 자원을 격리된 것처럼 사용할 수 있는 것이다.
cgroups(Control Groups)는 자원(resources)에 대한 제어를 가능하게 해주는 리눅스 커널의 기능이다.
cgroups는 다음 리소스를 제어할 수 있다.
- 메모리
- CPU
- I/O
- 네트워크
- device 노드(/dev/)
cgroup 드라이버
Control group은 프로세스에 할당된 리소스를 제한하는데 사용된다.
리눅스 배포판의 init 시스템이 systemd인 경우,
init 프로세스는 root control group(cgroup)을 생성 및 사용하는 cgroup 관리자로 작동한다.
Systemd는 cgroup과의 긴밀한 통합을 통해 프로세스당 cgroup을 할당한다.
그리고 cgroup 드라이버로 cgroupfs가 존재하는데,
컨테이너 런타임과 kubelet만이 cgroupfs를 사용하도록 설정할 수 있다.
systemd와 함께 cgroupfs를 사용하면 두 개의 서로 다른 cgroup 관리자가 존재하게 된다는 뜻이다.
- cgroupfs driver
cgroupfs는 cgroup을 제어하기 위해 만들어진 특수한 file system 방식 - systemd driver
systemd 자체가 init process 역할도 하면서, cgroup 또한 제어
단일 cgroup 관리자는 할당되는 리소스가 무엇인지를 단순화하고, 기본적으로 사용할 수 있는 리소스와 사용 중인 리소스를 일관성있게 볼 수 있다.
시스템에 두 개의 cgroup 관리자가 있으면, 이런 리소스도 두 개의 관점에서 보게 된다.
그런데 실무에서 kubelet과 도커에 cgroupfs를 사용하고, 나머지 프로세스는 systemd를 사용하도록 노드가 설정된 경우, 리소스가 부족할 때 불안정해지는 사례가 있다고 한다.
문제를 해결하기 위해서 컨테이너 런타임과 kubelet의 cgroup 드라이버로 systemd를 선택하도록 설정을 변경하면 시스템을 안정화 할 수 있다.
도커(컨테이너 런타임)에 대해 cgroup을 systemd로 구성하려면, native.cgroupdriver=systemd를 설정한다.
(설정 방법은 아래에.)
k8s나 docker를 접하게 되면, cgroup driver를 cgroupfs 또는 systemd로 설정하는 부분을 마주하게 된다.
이 때 cgroup을 systemd로 맞추는 것을 권장하고, 이는 위에서 언급했듯이 시스템을 안정적으로 운영하기 위함이다.
설정
$ sudo vi /usr/lib/systemd/system/docker.service
아래 docker.service 파일에서
ExecStart=/usr/bin/dockerd --exec-opt native.cgroupdriver=systemd
ExecStart 부분을 위와 같이 바꿔주고 저장한다.
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target docker.socket firewalld.service containerd.service
Wants=network-online.target
Requires=docker.socket containerd.service
[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 --exec-opt native.cgroupdriver=systemd
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutSec=0
RestartSec=2
Restart=always
# Note that StartLimit* options were moved from "Service" to "Unit" in systemd 229.
# Both the old, and new location are accepted by systemd 229 and up, so using the old location
# to make them work for either version of systemd.
StartLimitBurst=3
# Note that StartLimitInterval was renamed to StartLimitIntervalSec in systemd 230.
# Both the old, and new name are accepted by systemd 230 and up, so using the old name to make
# this option work for either version of systemd.
StartLimitInterval=60s
# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
# Comment TasksMax if your systemd version does not support it.
# Only systemd 226 and above support this option.
TasksMax=infinity
# set delegate yes so that systemd does not reset the cgroups of docker containers
Delegate=yes
# kill only the docker process, not all processes in the cgroup
KillMode=process
OOMScoreAdjust=-500
[Install]
WantedBy=multi-user.target
ExecStart 부분을 수정했다면 :wq로 저장하고 나오자.
아래 명령어를 순서대로 입력한다.
$ sudo systemctl daemon-reload
$ sudo systemctl restart docker
$ docker info | grep "Cgroup Driver"
Cgroup Driver: systemd
맨 아래 출력처럼 나온다면 성공이다.
K8s 설치
$ sudo kubeadm init --pod-network-cidr=192.168.0.0/16
...
Your Kubernetes control-plane has initialized successfully!
아래 작업을 통해 kubectl 권한을 획득한다.
$ 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, kubectl get all -A
명령어를 입력해서 기본 컴포넌트들이 잘 만들어졌는지 확인한다.
$ kubectl get node
NAME STATUS ROLES AGE VERSION
ip-172-31-43-149 Ready control-plane,master 29s v1.23.5
$ kubectl get all -A
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system pod/coredns-64897985d-8j9sl 0/1 ContainerCreating 0 2m31s
kube-system pod/coredns-64897985d-pt4gh 0/1 ContainerCreating 0 2m31s
kube-system pod/etcd-ip-172-31-43-149 1/1 Running 3 2m36s
kube-system pod/kube-apiserver-ip-172-31-43-149 1/1 Running 3 2m36s
kube-system pod/kube-controller-manager-ip-172-31-43-149 1/1 Running 3 2m36s
kube-system pod/kube-proxy-gjc47 1/1 Running 0 2m31s
kube-system pod/kube-scheduler-ip-172-31-43-149 1/1 Running 3 2m36s
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 2m38s
kube-system service/kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 2m37s
NAMESPACE NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
kube-system daemonset.apps/kube-proxy 1 1 1 1 1 kubernetes.io/os=linux 2m36s
NAMESPACE NAME READY UP-TO-DATE AVAILABLE AGE
kube-system deployment.apps/coredns 0/2 2 0 2m37s
NAMESPACE NAME DESIRED CURRENT READY AGE
kube-system replicaset.apps/coredns-64897985d 2 2 0 2m32s
coredns ContainerCreating 에러가 발생할 것이다
CNI 설정이 제대로 되지 않아서 그런것이므로
CNI를 calico로 설정해주면 해결할 수 있다.
$ curl https://projectcalico.docs.tigera.io/manifests/calico.yaml -O
$ kubectl apply -f calico.yaml
// master 노드에는 기본적으로 pod가 생성되지 않는데, 제한을 풀어주는 명령어(taint)
$ kubectl taint nodes --all node-role.kubernetes.io/master-
설치 완료 확인
$ kubectl get all -A
NAMESPACE NAME READY STATUS RESTARTS AGE
calico-apiserver pod/calico-apiserver-8749ccd5-vbmzk 1/1 Running 0 4m5s
calico-apiserver pod/calico-apiserver-8749ccd5-x7k2w 1/1 Running 0 4m5s
calico-system pod/calico-kube-controllers-67f85d7449-gwxhm 1/1 Running 0 5m6s
calico-system pod/calico-node-77xh2 1/1 Running 0 5m6s
calico-system pod/calico-typha-5758d546fc-f7vkb 1/1 Running 0 5m6s
kube-system pod/coredns-64897985d-8sjs2 1/1 Running 0 5m38s
kube-system pod/coredns-64897985d-lbg6g 1/1 Running 0 5m38s
kube-system pod/etcd-ip-172-31-43-149 1/1 Running 4 5m49s
kube-system pod/kube-apiserver-ip-172-31-43-149 1/1 Running 4 5m49s
kube-system pod/kube-controller-manager-ip-172-31-43-149 1/1 Running 0 5m52s
kube-system pod/kube-proxy-bmmqx 1/1 Running 0 5m38s
kube-system pod/kube-scheduler-ip-172-31-43-149 1/1 Running 4 5m49s
tigera-operator pod/tigera-operator-b876f5799-mv2lk 1/1 Running 0 5m29s
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
calico-apiserver service/calico-api ClusterIP 10.108.215.250 <none> 443/TCP 4m5s
calico-system service/calico-kube-controllers-metrics ClusterIP 10.108.221.232 <none> 9094/TCP 4m13s
calico-system service/calico-typha ClusterIP 10.110.229.56 <none> 5473/TCP 5m6s
default service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 5m53s
kube-system service/kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 5m50s
NAMESPACE NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
calico-system daemonset.apps/calico-node 1 1 1 1 1 kubernetes.io/os=linux 5m6s
kube-system daemonset.apps/kube-proxy 1 1 1 1 1 kubernetes.io/os=linux 5m50s
NAMESPACE NAME READY UP-TO-DATE AVAILABLE AGE
calico-apiserver deployment.apps/calico-apiserver 2/2 2 2 4m5s
calico-system deployment.apps/calico-kube-controllers 1/1 1 1 5m6s
calico-system deployment.apps/calico-typha 1/1 1 1 5m6s
kube-system deployment.apps/coredns 2/2 2 2 5m50s
tigera-operator deployment.apps/tigera-operator 1/1 1 1 5m29s
NAMESPACE NAME DESIRED CURRENT READY AGE
calico-apiserver replicaset.apps/calico-apiserver-8749ccd5 2 2 2 4m5s
calico-system replicaset.apps/calico-kube-controllers-67f85d7449 1 1 1 5m6s
calico-system replicaset.apps/calico-typha-5758d546fc 1 1 1 5m6s
kube-system replicaset.apps/coredns-64897985d 2 2 2 5m38s
tigera-operator replicaset.apps/tigera-operator-b876f5799 1 1 1 5m29s
레퍼런스
'DevOps > Kubernetes' 카테고리의 다른 글
Kubernetes, GitHub Actions, ArgoCD를 사용한 자동화 CI/CD 파이프라인 구축기 (1) | 2022.11.02 |
---|---|
Kubeadm 으로 K8s 설치하기 with 자동화 스크립트 (3) | 2022.06.10 |
[kubernetes] Helm으로 nginx ingress controller 설치하기 (1) | 2022.04.04 |
[Kubernetes] No Ingressclass resource with name nginx found 문제 해결하기 (Helm stable repo) (0) | 2022.03.31 |
[kubernetes] #10 쿠버네티스 영속성 데이터와 볼륨 (0) | 2022.03.14 |