Kubernetes 설치

아재발자·2025년 11월 29일

토이 프로젝트

목록 보기
2/2

해당 글은 개인으로 사용하는 미니 PC에 Kubernetes를 설치하고, 기본적인 설정을 다룬 내용을 간략하게 정리한 글입니다.

관련해서 왜 이렇게 설치를 했는지에 대해서는 지속적으로 추가 업데이트 할 예정입니다.

초기 설정

OS 설정

SELinux 설정

쿠버네티스는 기본적으로 SELinux Mode가 permissive로 설정되어 있어야 합니다.
( 관련 문서: installing-kubeadm-kubelet-and-kubectl )

따라서 아래의 명령어를 통해 SELinux 설정을 변경해줍니다.

# Set SELinux in permissive mode (effectively disabling it)
sudo setenforce 0
sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config

swapconfig

그리고 kubelet은 스왑 메모리가 감지되면 정상적으로 동작하지 않습니다.
( 관련 문서: install-kubeadm )

따라서 아래 명령어를 통해 스왑 메모리 설정을 비활성화시켜 줍니다.

sudo swapoff -a

ip_forward 설정

net.ipv4.ip_forward 옵션은 리눅스 커널이 IPv4 패킷을 다른 인터페이스로 라우팅할 지에 대한 여부를 설정하는 옵션입니다.

쿠버네티스는 기본적으로 CNI를 통해 Pod / Node간 통신을 처리하는 구조로 되어있기 때문에, 라우팅/포워딩을 할 수 있도록 1로 설정해줍니다.

sudo sysctl -w net.ipv4.ip_forward=1

만약 이 설정을 하지 않을 경우 컨트롤 플레인 초기화 시 아래와 같은 에러가 발생할 수 있습니다.

[ERROR FileContent--proc-sys-net-ipv4-ip_forward]: /proc/sys/net/ipv4/ip_forward contents are not set to 1

firewalld disabled

쿠버네티스는 기본적으로 사용되는 포트가 존재합니다.

이 중 Kubernetes API server 포트와 Kubelet API 포트는 필수적으로 사용되는 포트이기 때문에 OS 방화벽에서 해당 포트들을 허용처리 해주어야 합니다.

쿠버네티스에서 기본적으로 사용되는 포트와 MySQL, Redis 등을 사용할 때 마다 방화벽을 설정하는 것도 좋지만, 이번 글에서는 귀찮으므로 OS 방화벽 설정을 해제하는 방법으로 진행하고자 합니다.

systemctl stop firewalld
systemctl disable firewalld

만약 이러한 설정을 하지 않을 경우 컨트롤 플레인 초기화 시 아래와 같은 에러가 발생할 수 있습니다.

[WARNING Firewalld]: firewalld is active, please ensure ports [6443 10250] are open or your cluster may not function correctly

containerd 설치

쿠버네티스는 기본적으로 Pod에서 컨테이너를 실행시키기 위해 container runtime을 사용합니다.

사용할 수 있는 Container Runtime 목록

  • containerd
  • CRI-O
  • Docker Engine
  • Mirantis Container Runtime

그리고 이 글에서는 containerd를 사용하는 방법으로 진행합니다.

dnf Repository 추가

sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

containerd.io 설치

sudo dnf install containerd.io

containerd 설정 제거

mv /etc/containerd/config.toml /etc/containerd/config.toml.bak # 삭제하지 않고 bakup으로 보관

service containerd restart

만약 이러한 설정을 하지 않을 경우 컨트롤 플레인 초기화 시 아래와 같은 에러가 발생할 수 있습니다.

[preflight] WARNING: Couldn't create the interface used for talking to the container runtime: failed to create new CRI runtime service: validate service connection: validate CRI v1 runtime API for endpoint "unix:///var/run/containerd/containerd.sock": rpc error: code = Unimplemented desc = unknown service runtime.v1.RuntimeService

Kubernetes 설치

kubernetes 저장소 추가

cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/v1.34/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/v1.34/rpm/repodata/repomd.xml.key
EOF

kubelet, kubeadm, kubectl 설치

dnf install kubelet kubeadm kubectl

컨트롤 플레인 초기화

kubeadm init --apiserver-advertise-address={IP_ADDRESS}

아래와 같이 메세지가 응답되었다면 Kubernetes control-plane 초기 설정에 성공한 것입니다.

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/

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join {IP Address:Port} --token {token값} --discovery-token-ca-cert-hash {hash값}

그러면 안내를 따라서 아래의 명령을 실행해줍니다.

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

컨트롤 플레인 노드에서 Pod를 실행할 수 있게 taint 설정

쿠버네티스는 기본적으로 컨트롤 플레인과 워커 노드로 구성됩니다.

기본적으로 컨트롤 플레인 노드는 클러스터의 운영, 관리의 역할을 수행하기 때문에 Pod를 띄울 수 없으며, kubeadm init을 통해 컨트롤 플레인을 구성하고, kubeadm join을 통해 워커 노드를 추가하여 Pod를 띄우는 것이 일반적인 방법입니다.

하지만 지금처럼 쿠버네티스를 단일 서버로 구성하는 경우 컨트롤 플레인 노드에서 Pod를 실행할 수 있게끔 taint를 변경해주어야 합니다.

kubectl taint nodes --all node-role.kubernetes.io/control-plane-

Calico 설치

참고 문서: https://kubernetes.io/docs/tasks/administer-cluster/network-policy-provider/calico-network-policy/

kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml

중간 과정 확인

kubectl get pods --all-namespaces
[root@localhost tmp]# kubectl get pods --all-namespaces
NAMESPACE              NAME                                                    READY   STATUS    RESTARTS   AGE
kube-system            calico-kube-controllers-b45f49df6-zq85q                 1/1     Running   0          35m
kube-system            calico-node-6qr5n                                       1/1     Running   0          35m
kube-system            coredns-66bc5c9577-mdvrd                                1/1     Running   0          42m
kube-system            coredns-66bc5c9577-pvwdq                                1/1     Running   0          42m
kube-system            etcd-localhost.localdomain                              1/1     Running   0          42m
kube-system            kube-apiserver-localhost.localdomain                    1/1     Running   0          42m
kube-system            kube-controller-manager-localhost.localdomain           1/1     Running   0          42m
kube-system            kube-proxy-lw4z6                                        1/1     Running   0          42m
kube-system            kube-scheduler-localhost.localdomain                    1/1     Running   0          42m
kubectl get services --all-namespaces
[root@localhost tmp]# kubectl get services --all-namespaces
NAMESPACE              NAME                                   TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGE
default                kubernetes                             ClusterIP      10.96.0.1        <none>        443/TCP                      42m
kube-system            kube-dns                               ClusterIP      10.96.0.10       <none>        53/UDP,53/TCP,9153/TCP       42m

helm 설치

sudo dnf install helm

helm Repository 추가

helm repo add kubernetes-dashboard https://kubernetes.github.io/dashboard/

ingress-nginx 설치

helm upgrade --install ingress-nginx ingress-nginx \
  --repo https://kubernetes.github.io/ingress-nginx \
  --namespace ingress-nginx --create-namespace

Kubernetes Dashboard 설치

https://kubernetes.io/docs/tasks/access-application-cluster/web-ui-dashboard/

helm upgrade --install kubernetes-dashboard kubernetes-dashboard/kubernetes-dashboard --create-namespace --namespace kubernetes-dashboard

아래와 같이 나오면 성공입니다.

Release "kubernetes-dashboard" does not exist. Installing it now.
NAME: kubernetes-dashboard
LAST DEPLOYED: Sat Nov 29 00:13:33 2025
NAMESPACE: kubernetes-dashboard
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
*************************************************************************************************
*** PLEASE BE PATIENT: Kubernetes Dashboard may need a few minutes to get up and become ready ***
*************************************************************************************************

Congratulations! You have just installed Kubernetes Dashboard in your cluster.

To access Dashboard run:
  kubectl -n kubernetes-dashboard port-forward svc/kubernetes-dashboard-kong-proxy 8443:443

NOTE: In case port-forward command does not work, make sure that kong service name is correct.
      Check the services in Kubernetes Dashboard namespace using:
        kubectl -n kubernetes-dashboard get svc

Dashboard will be available at:
  https://localhost:8443

네트워크 설정

대시보드 ingress 추가

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
  annotations:
    nginx.ingress.kubernetes.io/backend-protocol: HTTPS
spec:
  ingressClassName: nginx
  rules:
  - host: {dashboard-host}
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: kubernetes-dashboard-kong-proxy
            port:
              number: 443

공유기 포트포워딩 설정

접속 테스트

ingress에서 설정한 {dashboard-host} 도메인으로 접속을 했을 때 아래와 같이 나오면 성공입니다.

https://{dashboard-host}

Bearer token 발급

Kubernetes Dashboard에 접속할 때 사용할 수 있는 인증 전략은 여러가지가 있습니다.

그 중 아주 기본적이고 간단하게 접속할 수 있는 Bearer token을 수동으로 발급받아 접속하는 방법으로 설명하려고 합니다.

ServiceAccount 생성

apiVersion: v1
kind: ServiceAccount
metadata:
  name: admin-user
  namespace: kubernetes-dashboard

---

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: admin-user
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: admin-user
  namespace: kubernetes-dashboard

Bearer Token 발급

kubectl -n kubernetes-dashboard create token admin-user
kubectl -n kubernetes-dashboard create token admin-user
{발급된 Bearer Token 어쩌구}

접속

발급된 Bearer Token을 입력 후 접속을 했을 때 아래와 같이 나온다면 성공입니다.

서비스 등록하기

아래처럼 서비스를 활성화 및 시작하여 OS가 재부팅될 때 자동으로 실행되게끔 처리합니다.

sudo systemctl enable containerd
sudo systemctl start containerd

sudo systemctl enable kubelet
sudo systemctl start kubelet
profile
안녕하세요. 아재 개발자입니다. 공부한 내용을 기록하고 잘못된 부분에 대해서 조언을 받기 위해 velog를 시작했습니다. :)

0개의 댓글