쿠버네티스
Devops
블로그 불러오는 중...
쿠버네티스
Devops
RKE2는 Rancher에서 개발한 기업용 차세대 Kubernetes 배포판입니다. RKE Government라고도 불립니다. 이는 미국 연방 정부 부문의 보안 및 규정 준수에 중점을 둔 완벽한 Kubernetes 배포판 입니다.
RKE2 라는 것은 보안이 강화된, 경량화된 쿠버네티스 배포판이라고 한다. 보안 부분에서는 보안을 달성하기 위해 다음과 같은 항목을 만족한다고 한다.
RKE2 라는 것을 처음 들어보는데, 한번 실습을 통해 구성요소나 원리를 파악해 볼 예정이다.
# systemd 기반 시스템에 서비스로 편리하게 설치할 수 있는 설치 스크립트를 제공 : 서비스와 바이너리 파일이 컴퓨터에 설치
# https://docs.rke2.io/install/methods
curl -sfL https://get.rke2.io --output install.sh
chmod +x install.sh
INSTALL_RKE2_CHANNEL=v1.33 ./install.sh
...
Installed:
rke2-common-1.33.7~rke2r3-0.el9.aarch64 rke2-selinux-0.22-1.el9.noarch rke2-server-1.33.7~rke2r3-0.el9.aa
# rke2 버전 확인
rke2 --version
rke2 version v1.33.7+rke2r3 (7e4fd1a82edf497cab91c220144619bbad659cf4)
go version go1.24.11 X:boringcrypto
# repo 추가 확인
dnf repolist
rancher-rke2-1.33-stable Rancher RKE2 1.33 (v1.33)
rancher-rke2-common-stable Rancher RKE2 Common (v1.33)
tree /etc/yum.repos.d/
cat /etc/yum.repos.d/rancher-rke2.repo
[rancher-rke2-common-stable]
name=Rancher RKE2 Common (v1.33)
baseurl=https://rpm.rancher.io/rke2/stable/common/centos/9/noarch
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://rpm.rancher.io/public.key
[rancher-rke2-1.33-stable]
name=Rancher RKE2 1.33 (v1.33)
baseurl=https://rpm.rancher.io/rke2/stable/1.33/centos/9/aarch64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://rpm.rancher.io/public.key
# 디렉터리 생성 확인
tree /etc/rancher/
tree /var/lib/rancher/
# rke2 명령 확인
# https://docs.rke2.io/install/configuration#running-the-binary-directly
# rke2 server : Run the RKE2 management server, which will also launch the Kubernetes control plane components such as the API server, controller-manager, and scheduler. Only Supported on Linux.
# rke2 agent : Run the RKE2 node agent. This will cause RKE2 to run as a worker node, launching the Kubernetes node services kubelet and kube-proxy. Supported on Linux and Windows.
rke2 --h
server Run management server
agent Run node agent
# RKE2 설정 : cni 플러그인(canal) 등
# https://docs.rke2.io/install/configuration
# https://docs.rke2.io/advanced
cat << EOF > /etc/rancher/rke2/config.yaml
write-kubeconfig-mode: "0644"
debug: true
cni: canal
bind-address: 192.168.10.11
advertise-address: 192.168.10.11
node-ip: 192.168.10.11
disable-cloud-controller: true
disable:
- servicelb
- rke2-coredns-autoscaler
- rke2-ingress-nginx
- rke2-snapshot-controller
- rke2-snapshot-controller-crd
- rke2-snapshot-validation-webhook
EOF
cat /etc/rancher/rke2/config.yaml
# canal cni 플러그인 helm chart values 파일 작성
# https://docs.rke2.io/networking/basic_network_options
# https://github.com/rancher/rke2-charts/blob/main-source/packages/rke2-canal/charts/values.yaml
mkdir -p /var/lib/rancher/rke2/server/manifests/
cat << EOF > /var/lib/rancher/rke2/server/manifests/rke2-canal-config.yaml
apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
name: rke2-canal
namespace: kube-system
spec:
valuesContent: |-
flannel:
iface: "enp0s9"
EOF
# coredns 의 autoscaler 미설치를 위한 helm chart values 파일 작성
# https://docs.rke2.io/add-ons/helm#customizing-packaged-components-with-helmchartconfig
# https://github.com/rancher/rke2-charts/tree/main/charts/rke2-coredns/rke2-coredns/1.45.200
cat << EOF > /var/lib/rancher/rke2/server/manifests/rke2-coredns-config.yaml
apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
name: rke2-coredns
namespace: kube-system
spec:
valuesContent: |-
autoscaler:
enabled: false
EOF
# 모니터링 : 신규 터미널창
watch -d pstree -a
journalctl -u rke2-server -f
# RKE2 시작 : 2분 정도 소요 -> coredns 파드까지 정상화 대략 1~2분 추가 소요
systemctl enable --now rke2-server.service
systemctl status rke2-server --no-pager
# 프로세스 확인
pstree -a | grep -v color | grep 'rke2$' -A5
pstree -a | grep -v color | grep 'containerd-shim ' -A2
# 자격증명 파일 복사
mkdir ~/.kube
ls -l /etc/rancher/rke2/rke2.yaml
cp /etc/rancher/rke2/rke2.yaml ~/.kube/config
# /etc/rancher 디렉터리 확인
tree /etc/rancher/
cat /etc/rancher/node/password
cat /etc/rancher/rke2/config.yaml
cat /etc/rancher/rke2/rke2-pss.yaml
# 바이너리 파일 확인
tree /var/lib/rancher/rke2/bin/
├── containerd
├── containerd-shim-runc-v2
├── crictl
├── ctr
├── kubectl
├── kubelet
└── runc
# PATH 안 건드리고 표준 위치로 바이너리 노출 설정 : 심볼릭 링크 방식
ln -s /var/lib/rancher/rke2/bin/containerd /usr/local/bin/containerd
ln -s /var/lib/rancher/rke2/bin/kubectl /usr/local/bin/kubectl
ln -s /var/lib/rancher/rke2/bin/crictl /usr/local/bin/crictl
ln -s /var/lib/rancher/rke2/bin/runc /usr/local/bin/runc
ln -s /var/lib/rancher/rke2/bin/ctr /usr/local/bin/ctr
ln -s /var/lib/rancher/rke2/agent/etc/crictl.yaml /etc/crictl.yaml
runc --version
containerd --version
kubectl version
# 편의성 설정
source <(kubectl completion bash)
alias k=kubectl
complete -F __start_kubectl k
echo 'source <(kubectl completion bash)' >> /etc/profile
echo 'alias k=kubectl' >> /etc/profile
echo 'complete -F __start_kubectl k' >> /etc/profile
k9s
# 확인
kubectl cluster-info -v=6
Kubernetes control plane is running at https://192.168.10.11:6443
# 노드, 파드 정보 확인
kubectl get node -owide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
k8s-node1 Ready control-plane,etcd 15m v1.34.3+rke2r3 192.168.10.11 <none> Rocky Linux 9.6 (Blue Onyx) 5.14.0-570.52.1.el9_6.aarch64 containerd://2.1.5-k3s1
helm list -A
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
rke2-canal kube-system 1 2026-02-09 14:30:45.002896818 +0000 UTC deployed rke2-canal-v3.31.3-build2026011900 v3.31.3
rke2-coredns kube-system 1 2026-02-09 14:30:44.989504642 +0000 UTC deployed rke2-coredns-1.45.008 1.13.1
rke2-metrics-server kube-system 1 2026-02-09 14:31:13.07011618 +0000 UTC deployed rke2-metrics-server-3.13.006 0.8.0
rke2-runtimeclasses kube-system 1 2026-02-09 14:31:17.059719859 +0000 UTC deployed rke2-runtimeclasses-0.1.000 0.1.0
kubectl get pod -A
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system etcd-k8s-node1 1/1 Running 0 2m31s
kube-system helm-install-rke2-canal-8ck96 0/1 Completed 0 2m42s
kube-system helm-install-rke2-coredns-mhw4x 0/1 Completed 0 2m42s
kube-system helm-install-rke2-metrics-server-rhqcp 0/1 Completed 0 2m42s
kube-system helm-install-rke2-runtimeclasses-7m69w 0/1 Completed 0 2m42s
kube-system kube-apiserver-k8s-node1 1/1 Running 0 2m31s
kube-system kube-controller-manager-k8s-node1 1/1 Running 0 2m31s
kube-system kube-proxy-k8s-node1 1/1 Running 0 2m31s
kube-system kube-scheduler-k8s-node1 1/1 Running 0 2m31s
kube-system rke2-canal-dkw2n 2/2 Running 0 2m22s
kube-system rke2-coredns-rke2-coredns-784bcb7f4d-tpt2d 1/1 Running 0 2m22s
kube-system rke2-metrics-server-7b59bd8854-m5w2c 1/1 Running 0 114s/etc/rancher/rke2/config.yaml 를 수정해서 클러스터 설정할 수 있다.
cni 는 canal 을 쓰고, 우리는 온프렘이므로 disable-cloud-controller 를 true 로 설정해 준다.
또 추가로 불필요한 기능들을 추가로 제거 한다.
추가로 canal 플러그인의 경우 flannel + calico 의 조합이라고 한다. 해당 부분도 설정을 추가한다.
워커 노드를 추가하기 위해 먼저 노드토큰을 알아야 한다.
[root@k8s-node1 ~]# cat /var/lib/rancher/rke2/server/node-token
K10c2d44abc26fe67ca8601a3bb13bbd70ab2eb8db0db874e924e163a47dbdf7e55::server:10f2d8b992bed2e83291d152214cd40dk8s-node2 로 간다. 그리고 워커 노드를 추가한다.
위에서 발견했던 token 을 가지고 설치해야 한다.
# Run the installer
curl -sfL https://get.rke2.io | INSTALL_RKE2_TYPE="agent" INSTALL_RKE2_CHANNEL=v1.33 sh -
# Configure the rke2-agent service : rke-agent 설정 파일 작성
## The rke2 server process listens on port 9345 for new nodes to register.
TOKEN=K10c2d44abc26fe67ca8601a3bb13bbd70ab2eb8db0db874e924e163a47dbdf7e55::server:10f2d8b992bed2e83291d152214cd40d
mkdir -p /etc/rancher/rke2/
cat << EOF > /etc/rancher/rke2/config.yaml
server: https://192.168.10.11:9345
token: $TOKEN
EOF
cat /etc/rancher/rke2/config.yaml
# Enabled/Start the service
systemctl enable --now rke2-agent.service
journalctl -u rke2-agent -f위에 노드 토큰을 가지고 설치를 한다.
노드가 연결되었으면, 노드를 확인해 본다.
kubectl get node -owide
kubectl get pod -n kube-system -owide | grep k8s-node2

k8s-node2 로 가서 설치된 파일들의 목록을 확인하고 구성요소들을 tree 로 확인해 본다.
# 디렉터리 확인
tree /var/lib/rancher/rke2 -L 1
├── agent
├── bin -> /var/lib/rancher/rke2/data/v1.34.3-rke2r3-5b8349de68df/bin # 바이너리 파일
├── data # bin, charts
└── server # 서버 역할이 아니여서 아무것도 없음
# rke2-agent
systemctl status rke2-agent.service --no-pager
cat /usr/lib/systemd/system/rke2-agent.service
pstree -al
├─rke2
│ ├─containerd -c /var/lib/rancher/rke2/agent/etc/containerd/config.toml
│ │ └─10*[{containerd}]
│ ├─kubelet --volume-plugin-dir=/var/lib/kubelet/volumeplugins --file-check-frequency=5s --sync-frequency=30s --config-dir=/var/lib/rancher/rke2/agent/etc/kubelet.conf.d --containerd=/run/k3s/containerd/containerd.sock --hostname-override=k8s-node2 --kubeconfig=/var/lib/rancher/rke2/agent/kubelet.kubeconfig --node-labels= --read-only-port=0
│ │ └─11*[{kubelet}]
│ └─10*[{rke2}]
# PATH 안 건드리고 표준 위치로 노출 설정 : 심볼릭 링크 방식
ln -s /var/lib/rancher/rke2/bin/containerd /usr/local/bin/containerd
ln -s /var/lib/rancher/rke2/bin/crictl /usr/local/bin/crictl
ln -s /var/lib/rancher/rke2/agent/etc/crictl.yaml /etc/crictl.yaml
crictl ps
crictl images
#
tree /etc/rancher/
├── node
│ └── password
└── rke2
├── config.yaml
└── rke2-pss.yaml
# agent 디렉터리
tree /var/lib/rancher/rke2/agent/ -L 3
...
├── containerd
│ ├── bin
...
├── etc
│ ├── containerd
│ │ └── config.toml
│ ├── crictl.yaml
│ ├── kubelet.conf.d
│ │ └── 00-rke2-defaults.conf
│ ├── rke2-agent-load-balancer.json
│ └── rke2-api-server-agent-load-balancer.json
├── images
│ ├── kube-proxy-image.txt
│ └── runtime-image.txt
├── kubelet.kubeconfig
├── kubeproxy.kubeconfig
├── logs
│ └── kubelet.log
├── pod-manifests
│ └── kube-proxy.yaml
├── rke2controller.kubeconfig
├── server-ca.crt
├── serving-kubelet.crt
└── serving-kubelet.key
##
cat /var/lib/rancher/rke2/agent/etc/containerd/config.toml
cat /var/lib/rancher/rke2/agent/etc/kubelet.conf.d/00-rke2-defaults.conf
address: 0.0.0.0
allowedUnsafeSysctls:
- net.ipv4.ip_forward
- net.ipv6.conf.all.forwarding
...
## 워커 노드를 컨트롤 플레인에 등록 시 서버 주소
cat /var/lib/rancher/rke2/agent/etc/rke2-agent-load-balancer.json | jq
"ServerURL": "https://192.168.10.11:9345",
"ServerAddresses": [
"192.168.10.11:9345"
## 컨트롤 플레인 k8s apiserver 서버 주소
cat /var/lib/rancher/rke2/agent/etc/rke2-api-server-agent-load-balancer.json | jq
"ServerURL": "https://192.168.10.11:6443",
"ServerAddresses": [
"192.168.10.11:6443"
## static pod : kube-proxy
cat /var/lib/rancher/rke2/agent/pod-manifests/kube-proxy.yaml
...k8s-node1 에서 다음과 같은 명령어로 node를 제거한다. 하기 명령어는 삭제보단 쿠버네티스 내에서 노드를 제거하는 명령어 이다.
kubectl drain k8s-node2 --ignore-daemonsets --delete-emptydir-data
# Kubernetes 클러스터에서 노드 제거 : 파드가 다 빠진 거 확인 후
kubectl delete node k8s-node2k8s-node2 에서 실제로 삭제하는 명령어 이다.
# RKE2 서비스 중지
systemctl stop rke2-agent
# 삭제 스크립트 확인
ls -l /usr/bin/rke2*
-rwxr-xr-x. 1 root root 119597592 Feb 5 04:44 /usr/bin/rke2
-rwxr-xr-x. 1 root root 3430 Feb 5 23:02 /usr/bin/rke2-killall.sh
-rwxr-xr-x. 1 root root 5573 Feb 5 23:02 /usr/bin/rke2-uninstall.sh
# RKE2 삭제 스크립트 실행 : 컨테이너, 네트워크 인터페이스, 관련 파일을 정리
cat /usr/bin/rke2-uninstall.sh
rke2-uninstall.sh
# 관련 디렉터리 삭제 확인
tree /etc/rancher
tree /var/lib/rancher하기 명령어로 삭제 이후 다시 설치도 위에 과정대로 진행하면 바로 설치가 된다.
# Run the installer
curl -sfL https://get.rke2.io | INSTALL_RKE2_TYPE="agent" INSTALL_RKE2_CHANNEL=v1.33 sh -
# Configure the rke2-agent service
TOKEN=K10c2d44abc26fe67ca8601a3bb13bbd70ab2eb8db0db874e924e163a47dbdf7e55::server:10f2d8b992bed2e83291d152214cd40d
mkdir -p /etc/rancher/rke2/
cat << EOF > /etc/rancher/rke2/config.yaml
server: https://192.168.10.11:9345
token: $TOKEN
EOF
cat /etc/rancher/rke2/config.yaml
# Enabled/Start the service
systemctl enable --now rke2-agent.service
journalctl -u rke2-agent -f해당 방식대로 아주 간단히 노드를 추가 + 제거 할 수 있는 것을 확인해 보았다.
인증서를 수동 교체하려면 rke 프로세스를 먼저 중단을 시켜야 한다.
systemctl stop rke2-server
# Rotate certificates
rke2 certificate rotate
# 시간이 조금 소요된다
systemctl start rke2-server
# 확인
rke2 certificate check --output table
# kubeconfig 갱신
diff /etc/rancher/rke2/rke2.yaml ~/.kube/config
yes | cp /etc/rancher/rke2/rke2.yaml ~/.kube/config ; echo
kubectl cluster-inforke2 의 경우에 새 버전으로 업그레이드 시 kubernetes 와 같이 편차 정책이 적용되므로 마이너 버전을 건너 뛰지 못한다.
링크를 통해 릴리즈 버전 등을 확인할 수 있다.
INSTALL_RKE2_VERSION : GitHub에서 다운로드할 RKE2 버전 - stable(기본값),INSTALL_RKE2_TYPE : 생성할 systemd 서비스의 유형 - server(기본값), agentINSTALL_RKE2_CHANNEL_URL : RKE2 다운로드 URL을 가져오기 위한 채널 URL - https://update.rke2.io/v1-release/channels (기본값)INSTALL_RKE2_CHANNEL : RKE2 다운로드 URL을 가져오는 데 사용할 채널 - stable(기본값), latest, testingINSTALL_RKE2_METHOD : 사용할 설치 방법 - rpm(RPM 기반 시스템 경우 기본값), tar(그외 경우 기본값)방식에는 스크립트방식과 RPM 업그레이드, 바이너리 업그레이드 방식이 있다.
실습에서는 컨트롤 노드를 업그레이드 하고, 그 이후 워커노드를 업그레이드 한다.
현재 노드는 1.33.8 이다. 목표는 1.34 이다.
# 모니터링
while true; do curl -s http://192.168.10.12:30000 | grep Hostname; date; sleep 1; done
watch -d "kubectl get pod -n kube-system -owide --sort-by=.metadata.creationTimestamp | tac"
watch -d "kubectl get node"
watch -d etcdctl \
--endpoints=https://127.0.0.1:2379 \
--cacert=/var/lib/rancher/rke2/server/tls/etcd/server-ca.crt \
--cert=/var/lib/rancher/rke2/server/tls/etcd/client.crt \
--key=/var/lib/rancher/rke2/server/tls/etcd/client.key \
member list --write-out=table# 버전 정보 확인
kubectl get node
rke2 --version
rke2 version v1.33.7+rke2r3 (7e4fd1a82edf497cab91c220144619bbad659cf4)
# 채널 정보 확인
curl -s https://update.rke2.io/v1-release/channels | jq .data
{
"id": "stable",
"type": "channel",
"links": {
"self": "https://update.rke2.io/v1-release/channels/stable"
},
"name": "stable",
"latest": "v1.34.3+rke2r3"
},
{
"id": "latest",
"type": "channel",
"links": {
"self": "https://update.rke2.io/v1-release/channels/latest"
},
"name": "latest",
"latest": "v1.35.0+rke2r3",
"latestRegexp": ".*",
"excludeRegexp": "(^[^+]+-|v1\\.25\\.5\\+rke2r1|v1\\.26\\.0\\+rke2r1)"
},
...
{
"id": "v1.34",
"type": "channel",
"links": {
"self": "https://update.rke2.io/v1-release/channels/v1.34"
},
"name": "v1.34",
"latest": "v1.34.3+rke2r3",
"latestRegexp": "v1\\.34\\..*",
"excludeRegexp": "^[^+]+-"
},
# v1.34 버전 업그레이드! : 아래 Running scriptlet 과정에서 업그레이드 수행됨, app 통신 영향 없었음.
curl -sfL https://get.rke2.io | INSTALL_RKE2_CHANNEL=v1.34 sh -
...
Running transaction
Preparing : 1/1
Upgrading : rke2-common-1.34.3~rke2r3-0.el9.aarch64 1/4
Upgrading : rke2-server-1.34.3~rke2r3-0.el9.aarch64 2/4
Running scriptlet: rke2-server-1.34.3~rke2r3-0.el9.aarch64 2/4
Running scriptlet: rke2-server-1.33.7~rke2r3-0.el9.aarch64 3/4
Cleanup : rke2-server-1.33.7~rke2r3-0.el9.aarch64 3/4
Running scriptlet: rke2-server-1.33.7~rke2r3-0.el9.aarch64 3/4
Running scriptlet: rke2-common-1.33.7~rke2r3-0.el9.aarch64 4/4
Cleanup : rke2-common-1.33.7~rke2r3-0.el9.aarch64 4/4
Running scriptlet: rke2-common-1.33.7~rke2r3-0.el9.aarch64 4/4
Verifying : rke2-common-1.34.3~rke2r3-0.el9.aarch64 1/4
Verifying : rke2-common-1.33.7~rke2r3-0.el9.aarch64 2/4
Verifying : rke2-server-1.34.3~rke2r3-0.el9.aarch64 3/4
Verifying : rke2-server-1.33.7~rke2r3-0.el9.aarch64 4/4 4/4
# 확인
rke2 --version
rke2 version v1.34.3+rke2r3 (7598946e0086a9131564ccbb3c142b3fa54516ad)
go version go1.24.11 X:boringcrypto
# 위 스크립트 설치 과정만으로 아래 처럼 파드들이 신규 재생성되었음
## 첫번쨰(etcd, apiserver, kube-proxy) -> 두번째(scheduler, kcm)
kubectl get pod -n kube-system --sort-by=.metadata.creationTimestamp | tac
helm-install-rke2-canal-jv2ml 0/1 Completed 0 2m41s
helm-install-rke2-coredns-tf6np 0/1 Completed 0 2m41s
helm-install-rke2-metrics-server-2pb6j 0/1 Completed 0 2m41s
helm-install-rke2-runtimeclasses-cslch 0/1 Completed 0 2m41s
kube-controller-manager-k8s-node1 1/1 Running 0 2m58s
kube-scheduler-k8s-node1 1/1 Running 0 2m58s
kube-proxy-k8s-node1 1/1 Running 0 3m52s
etcd-k8s-node1 1/1 Running 0 3m52s
kube-apiserver-k8s-node1 1/1 Running 1 (3m52s ago) 3m52s
rke2-canal-ktsqk 2/2 Running 0 21m
kube-proxy-k8s-node2 1/1 Running 0 21m
rke2-metrics-server-7b59bd8854-m5w2c 1/1 Running 0 76m
rke2-canal-dkw2n 2/2 Running 0 76m
rke2-coredns-rke2-coredns-784bcb7f4d-tpt2d 1/1 Running 0 76m
# repo 추가 및 기존 repo 삭제 확인
dnf repolist
rancher-rke2-1.34-stable Rancher RKE2 1.34 (v1.34)
rancher-rke2-common-stable Rancher RKE2 Common (v1.34)
tree /etc/yum.repos.d/
cat /etc/yum.repos.d/rancher-rke2.repo
cat /etc/yum.repos.d/rancher-rke2.repo | grep -iE 'name|baseurl'
name=Rancher RKE2 Common (v1.34)
baseurl=https://rpm.rancher.io/rke2/stable/common/centos/9/noarch
name=Rancher RKE2 1.34 (v1.34)
baseurl=https://rpm.rancher.io/rke2/stable/1.34/centos/9/aarch64
# kube-system 파드 별 컨테이너 이미지 정보 출력
kubectl get pods -n kube-system -o custom-columns="POD_NAME:.metadata.name,IMAGES:.spec.containers[*].image"
kubectl get pods -n kube-system \
-o custom-columns=\
POD:.metadata.name,\
CONTAINERS:.spec.containers[*].name,\
IMAGES:.spec.containers[*].image
# 설치 후 rke2 프로세스를 다시 시작 Remember to restart the rke2 process after installing:
systemctl restart rke2-server
# 노드 정보 확인
kubectl get node -owide
[root@k8s-node1 ~]# kubectl get node -owide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
k8s-node1 Ready control-plane,etcd,master 12h v1.34.4+rke2r1 192.168.10.11 <none> Rocky Linux 9.6 (Blue Onyx) 5.14.0-570.52.1.el9_6.aarch64 containerd://2.1.5-k3s1
k8s-node2 Ready <none> 12h v1.33.8+rke2r1 192.168.10.12 <none> Rocky Linux 9.6 (Blue Onyx) 5.14.0-570.52.1.el9_6.aarch64 containerd://2.1.5-k3s1공식 문서에서 해당 프로세스를 재시작 해야 한다고 해서 설치 이후에 프로세스를 restart 한다.
[k8s-node2]
# 특정 채널(예: 최신 버전)의 최신 버전으로 업그레이드하려면 해당 채널을 지정
rke2 --version
curl -sfL https://get.rke2.io | INSTALL_RKE2_TYPE=agent INSTALL_RKE2_CHANNEL=v1.34 sh -
# 확인
rke2 --version
rke2 version v1.34.3+rke2r3 (7598946e0086a9131564ccbb3c142b3fa54516ad)
go version go1.24.11 X:boringcrypto
# repo 추가 및 기존 repo 삭제 확인
dnf repolist
rancher-rke2-1.34-stable Rancher RKE2 1.34 (v1.34)
rancher-rke2-common-stable Rancher RKE2 Common (v1.34)
# 설치 후 rke2 프로세스를 다시 시작 : Agent nodes
systemctl restart rke2-agent워커 노드도 마찬가지로 업그레이드 후 프로세스 재시작이 필요하다.
kubectl get node -owide 로 버전을 확인해 본다.
업그레이드가 정상으로 된 것을 알 수 있다.
위에서 v1.34 로 업그레이드를 진행했다. v1.35 로 업그레이드 하는데, 이번에는 자동 스크립트로 실행해 본다.
시스템 업그레이드 컨트롤러를 설치한다.
# 설치
kubectl apply -f https://github.com/rancher/system-upgrade-controller/releases/latest/download/crd.yaml -f https://github.com/rancher/system-upgrade-controller/releases/latest/download/system-upgrade-controller.yaml
customresourcedefinition.apiextensions.k8s.io/plans.upgrade.cattle.io created
namespace/system-upgrade created
serviceaccount/system-upgrade created
role.rbac.authorization.k8s.io/system-upgrade-controller created
clusterrole.rbac.authorization.k8s.io/system-upgrade-controller created
clusterrole.rbac.authorization.k8s.io/system-upgrade-controller-drainer created
rolebinding.rbac.authorization.k8s.io/system-upgrade created
clusterrolebinding.rbac.authorization.k8s.io/system-upgrade created
clusterrolebinding.rbac.authorization.k8s.io/system-upgrade-drainer created
configmap/default-controller-env created
deployment.apps/system-upgrade-controller created
# 확인
kubectl get deploy,pod,cm -n system-upgrade
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/system-upgrade-controller 1/1 1 1 12m
NAME READY STATUS RESTARTS AGE
pod/system-upgrade-controller-6f9f9b8cf4-46n82 1/1 Running 0 12m
NAME DATA AGE
configmap/default-controller-env 10 12m
kubectl get crd | grep upgrade
plans.upgrade.cattle.io 2026-02-09T18:08:08Z
kubectl logs -n system-upgrade -l app.kubernetes.io/name=system-upgrade-controller -f
...plan 을 작성하면 crd 를 감시하다가 업그레이드를 진행한다. 하기 명령어로 CRD 를 추가하고 업그레이드 이후 노드 등을 확인해 본다.
# plan 작성 및 실행
cat << EOF | kubectl apply -f -
apiVersion: upgrade.cattle.io/v1
kind: Plan
metadata:
name: server-plan
namespace: system-upgrade
spec:
concurrency: 1
cordon: true
nodeSelector:
matchExpressions:
- key: node-role.kubernetes.io/control-plane
operator: In
values:
- "true"
serviceAccountName: system-upgrade
upgrade:
image: rancher/rke2-upgrade
channel: https://update.rke2.io/v1-release/channels/latest # version: v1.35.0+rke2r3 , curl -s https://update.rke2.io/v1-release/channels | jq .data
---
apiVersion: upgrade.cattle.io/v1
kind: Plan
metadata:
name: agent-plan
namespace: system-upgrade
spec:
concurrency: 1
cordon: true
nodeSelector:
matchExpressions:
- key: node-role.kubernetes.io/control-plane
operator: DoesNotExist
prepare:
args:
- prepare
- server-plan
image: rancher/rke2-upgrade
serviceAccountName: system-upgrade
upgrade:
image: rancher/rke2-upgrade
channel: https://update.rke2.io/v1-release/channels/latest
EOF해당 작업 이후 5분 이상이 소요되었고 중간에 kubectl 명령어가 timeout 걸릴 때도 있었다.
# 확인
kubectl get node -owide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
k8s-node1 Ready control-plane,etcd,master 108m v1.35.0+rke2r3 192.168.10.11 <none> Rocky Linux 9.6 (Blue Onyx) 5.14.0-570.52.1.el9_6.aarch64 containerd://2.1.5-k3s1
k8s-node2 Ready <none> 97m v1.35.0+rke2r3 192.168.10.12 <none> Rocky Linux 9.6 (Blue Onyx) 5.14.0-570.52.1.el9_6.aarch64 containerd://2.1.5-k3s1
#
kubectl -n system-upgrade get plans -o wide
NAME IMAGE CHANNEL VERSION COMPLETE MESSAGE APPLYING
agent-plan rancher/rke2-upgrade https://update.rke2.io/v1-release/channels/latest True
server-plan rancher/rke2-upgrade https://update.rke2.io/v1-release/channels/latest True
kubectl -n system-upgrade get jobs
NAME STATUS COMPLETIONS DURATION AGE
apply-agent-plan-on-k8s-node2-with-db1bffd09b601fca4c7c06-7dc30 Complete 1/1 2m5s 4m16s
apply-server-plan-on-k8s-node1-with-db1bffd09b601fca4c7c0-28ad1 Complete 1/1 55s 4m16s
kubectl get pod -n system-upgrade -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
apply-agent-plan-on-k8s-node2-with-db1bffd09b601fca4c7c06-54frb 0/1 Unknown 0 4m30s 192.168.10.12 k8s-node2 <none> <none>
apply-agent-plan-on-k8s-node2-with-db1bffd09b601fca4c7c06-jrsnq 0/1 Completed 0 2m37s 192.168.10.12 k8s-node2 <none> <none>
apply-server-plan-on-k8s-node1-with-db1bffd09b601fca4c7c0-xg4jl 0/1 Unknown 0 4m30s 192.168.10.11 k8s-node1 <none> <none>
apply-server-plan-on-k8s-node1-with-db1bffd09b601fca4c7c0-msrt2 0/1 Completed 0 3m43s 192.168.10.11 k8s-node1 <none> <none>
system-upgrade-controller-6f9f9b8cf4-zksgq 1/1 Running 0 8m20s 10.42.0.8 k8s-node1 <none> <none>
# job 에 의해 생성된 파드가 업그레이드 관련 수행을 시도하니, 해당 파드는 상당한 권한의 rbac과 호스트의 모든 / 경로를 마운트로 사용 가능해야 되는 것으로 보임
# 실행되는 업그레이드 작업은 기본 노드에 변경 사항을 적용하기 위해 높은 권한이 필요합니다. 기본적으로 다음과 같이 구성됩니다.
## Host IPC, NET, and PID namespaces + The CAP_SYS_BOOT capability + Host root mounted at /host with read and write permissions
kubectl describe pod -n system-upgrade |grep ^Volumes: -A4
Volumes:
host-root:
Type: HostPath (bare host directory volume)
Path: /
HostPathType: Directory
...
# 로그 확인
kubectl logs -n system-upgrade -l app.kubernetes.io/name=system-upgrade-controller
object="system-upgrade/server-plan" fieldPath="" kind="Plan" apiVersion="upgrade.cattle.io/v1" type="Normal" reason="Resolved" message="Resolved latest version from Spec.Channel: v1.35.0-rke2r3"
object="system-upgrade/server-plan" fieldPath="" kind="Plan" apiVersion="upgrade.cattle.io/v1" type="Normal" reason="SyncJob" message="Jobs synced for version v1.35.0-rke2r3 on Nodes k8s-node1. Hash: db1bffd09b601fca4c7c067d987c4d368f9237f8219289438d8678e8"
object="system-upgrade/server-plan" fieldPath="" kind="Plan" apiVersion="upgrade.cattle.io/v1" type="Normal" reason="JobComplete" message="Job completed on Node k8s-node1"
object="system-upgrade/server-plan" fieldPath="" kind="Plan" apiVersion="upgrade.cattle.io/v1" type="Normal" reason="Complete" message="Jobs complete for version v1.35.0-rke2r3. Hash: db1bffd09b601fca4c7c067d987c4d368f9237f8219289438d8678e8"
...
해당 실습화면처럼, 정상적으로 업그레이드 된 것을 볼 수 있다.
1. Cluster API (CAPI) Kubernetes 클러스터를 쿠버네티스 방식으로 생성·관리하기 위한 프로젝트입니다.
“쿠버네티스로 쿠버네티스 클러스터를 관리하는 도구”
📌 특징 선언형(Declarative) 방식으로 클러스터 관리
다양한 인프라 지원
📌 구성 요소
Cluster API는 다음 리소스들로 구성됩니다:
Cluster – 전체 클러스터 정의
ControlPlane – 마스터 노드 정의
MachineDeployment – 워커 노드 그룹
Machine – 개별 노드
2. clusterctl
clusterctl은 Cluster API를 설치하고 초기화하는 공식 CLI 도구입니다.
역할은
kind k8s 와 clusterctl 을 이용하여 실습을 진행한다.
위에 내용을 기준으로 클러스터 API를 실습한다. kind 가 설치된 것으로 생각하고 진행한다.
해당 실습은 kind 로 관리 쿠버네티스 클러스터를 만들고, 그 다음에 워커노드 클러스터를 설치하는 실습이다.
mkdir capi-docker && cd capi-docker
# (TS)
docker context ls
NAME DESCRIPTION DOCKER ENDPOINT ERROR
default Current DOCKER_HOST based configuration unix:///var/run/docker.sock
desktop-linux * Docker Desktop unix:///Users/chanki/.docker/run/docker.sock
# 중요! 혹시 미삭제 컨테이너 있는지 확인
docker ps -a
# k8s 설치
kind create cluster --name myk8s --image kindest/node:v1.35.0 --config - <<EOF
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
extraMounts:
- hostPath: /Users/chanki/.docker/run/docker.sock
containerPath: /var/run/docker.sock
extraPortMappings:
- containerPort: 30000 # sample
hostPort: 30000
- containerPort: 30001 # kube-ops-view
hostPort: 30001
EOF
# (옵션) kube-ops-view
helm repo add geek-cookbook https://geek-cookbook.github.io/charts/
helm install kube-ops-view geek-cookbook/kube-ops-view --version 1.2.2 \
--set service.main.type=NodePort,service.main.ports.http.nodePort=30001 \
--set env.TZ="Asia/Seoul" --namespace kube-system
open "http://127.0.0.1:30001/#scale=1.5"
# Install clusterctl
## mac 사용자
brew install clusterctl
## Windows WSL2 사용자 (Linux amd64)
curl -L https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.12.2/clusterctl-linux-amd64 -o clusterctl
sudo install -o root -g root -m 0755 clusterctl /usr/local/bin/clusterctl
## 버전 확인
clusterctl version -o json | jq
# [Docker 프로바이더] Initialize the management cluster : 현재 k8s 를 관리 클러스터로 변환
## Docker 프로바이더는 프로덕션 환경에 사용하도록 설계되지 않았으며 개발 환경 전용
## ClusterTopology관리형 토폴로지 및 ClusterClass 지원을 활성화하는 데 필요한 기능은 다음과 같이 활성화
## https://cluster-api.sigs.k8s.io/tasks/experimental-features/experimental-features
export CLUSTER_TOPOLOGY=true # Enable the experimental Cluster topology feature
clusterctl init --infrastructure docker # Initialize the management cluster
# 확인
## 관련 crd 설치
kubectl get crd
kubectl get crd | grep x-k8s
clusterclasses.cluster.x-k8s.io 2026-02-10T14:53:47Z
clusterresourcesetbindings.addons.cluster.x-k8s.io 2026-02-10T14:53:47Z
clusterresourcesets.addons.cluster.x-k8s.io 2026-02-10T14:53:47Z
clusters.cluster.x-k8s.io 2026-02-10T14:53:47Z
devclusters.infrastructure.cluster.x-k8s.io 2026-02-10T14:53:48Z
devclustertemplates.infrastructure.cluster.x-k8s.io 2026-02-10T14:53:48Z
devmachines.infrastructure.cluster.x-k8s.io 2026-02-10T14:53:48Z
devmachinetemplates.infrastructure.cluster.x-k8s.io 2026-02-10T14:53:48Z
dockerclusters.infrastructure.cluster.x-k8s.io 2026-02-10T14:53:48Z
dockerclustertemplates.infrastructure.cluster.x-k8s.io 2026-02-10T14:53:48Z
dockermachinepools.infrastructure.cluster.x-k8s.io 2026-02-10T14:53:48Z
dockermachinepooltemplates.infrastructure.cluster.x-k8s.io 2026-02-10T14:53:48Z
dockermachines.infrastructure.cluster.x-k8s.io 2026-02-10T14:53:48Z
dockermachinetemplates.infrastructure.cluster.x-k8s.io 2026-02-10T14:53:48Z
extensionconfigs.runtime.cluster.x-k8s.io 2026-02-10T14:53:47Z
ipaddressclaims.ipam.cluster.x-k8s.io 2026-02-10T14:53:47Z
ipaddresses.ipam.cluster.x-k8s.io 2026-02-10T14:53:47Z
kubeadmconfigs.bootstrap.cluster.x-k8s.io 2026-02-10T14:53:48Z
kubeadmconfigtemplates.bootstrap.cluster.x-k8s.io 2026-02-10T14:53:48Z
kubeadmcontrolplanes.controlplane.cluster.x-k8s.io 2026-02-10T14:53:48Z
kubeadmcontrolplanetemplates.controlplane.cluster.x-k8s.io 2026-02-10T14:53:48Z
machinedeployments.cluster.x-k8s.io 2026-02-10T14:53:47Z
machinedrainrules.cluster.x-k8s.io 2026-02-10T14:53:47Z
machinehealthchecks.cluster.x-k8s.io 2026-02-10T14:53:47Z
machinepools.cluster.x-k8s.io 2026-02-10T14:53:47Z
machines.cluster.x-k8s.io 2026-02-10T14:53:47Z
machinesets.cluster.x-k8s.io 2026-02-10T14:53:47Z
providers.clusterctl.cluster.x-k8s.io 2026-02-10T14:53:15Z
## capd-system, capi-(kueadm-X/Y, system), cert-manager 네임스페이스가 생성
kubectl get pod -A
NAMESPACE NAME READY STATUS RESTARTS AGE
capd-system capd-controller-manager-7c9d67ffdf-7npsd 1/1 Running 0 3m10s
capi-kubeadm-bootstrap-system capi-kubeadm-bootstrap-controller-manager-bd5f89bbd-9c9ng 1/1 Running 0 3m10s
capi-kubeadm-control-plane-system capi-kubeadm-control-plane-controller-manager-55c48d9b5-bckj5 1/1 Running 0 3m10s
capi-system capi-controller-manager-6cc7b949c4-rmd7h 1/1 Running 0 3m11s
cert-manager cert-manager-598d877b78-9lkmd 1/1 Running 0 3m37s
cert-manager cert-manager-cainjector-6b5777d564-7mfzz 1/1 Running 0 3m37s
cert-manager cert-manager-webhook-5d9fc6b4ff-slscg 1/1 Running 0 3m37s
...

설치 이후에, capd 로 시작하는 네임스페이스들이 추가가 되어 있다.
관리용 클러스터 정보를 확인해 본다.
## capd-system, capi-(kueadm-X/Y, system), cert-manager 네임스페이스가 생성
kubectl get pod -A
NAMESPACE NAME READY STATUS RESTARTS AGE
capd-system capd-controller-manager-7c9d67ffdf-7npsd 1/1 Running 0 3m10s
capi-kubeadm-bootstrap-system capi-kubeadm-bootstrap-controller-manager-bd5f89bbd-9c9ng 1/1 Running 0 3m10s
capi-kubeadm-control-plane-system capi-kubeadm-control-plane-controller-manager-55c48d9b5-bckj5 1/1 Running 0 3m10s
capi-system capi-controller-manager-6cc7b949c4-rmd7h 1/1 Running 0 3m11s
cert-manager cert-manager-598d877b78-9lkmd 1/1 Running 0 3m37s
cert-manager cert-manager-cainjector-6b5777d564-7mfzz 1/1 Running 0 3m37s
cert-manager cert-manager-webhook-5d9fc6b4ff-slscg 1/1 Running 0 3m37s
...
## Enabling Experimental Features 정보 확인 : ClusterTopology=true , InPlaceUpdates=false 등
kubectl describe -n capi-system deployment.apps/capi-controller-manager | grep feature-gates
--feature-gates=MachinePool=true,ClusterTopology=true,RuntimeSDK=false,MachineSetPreflightChecks=true,MachineWaitForVolumeDetachConsiderVolumeAttachments=true,PriorityQueue=false,ReconcilerRateLimiting=false,InPlaceUpdates=false,MachineTaintPropagation=false
# 프로바이더 (타입별)확인 : CAPI 구성요소가 설치된 상태
kubectl get providers.clusterctl.cluster.x-k8s.io -A
NAMESPACE NAME AGE TYPE PROVIDER VERSION
capd-system infrastructure-docker 5m30s InfrastructureProvider docker v1.12.2
capi-system cluster-api 5m31s CoreProvider cluster-api v1.12.2
capi-kubeadm-bootstrap-system bootstrap-kubeadm 5m31s BootstrapProvider kubeadm v1.12.2
capi-kubeadm-control-plane-system control-plane-kubeadm 5m31s ControlPlaneProvider kubeadm v1.12.2
# CAPI의 핵심 컨트롤러 집합 : Cluster / MachineDeployment / MachineSet / Machine CRD 관리, 전체 reconcile orchestration 담당
kubectl get providers -n capi-system cluster-api -o yaml
providerName: cluster-api
type: CoreProvider
version: v1.12.2
# 노드를 Kubernetes로 부팅시키는 역할 : cloud-init user-data 생성, kubeadm join/init config 생성
kubectl get providers -n capi-kubeadm-bootstrap-system bootstrap-kubeadm -o yaml
providerName: kubeadm
type: BootstrapProvider
version: v1.12.2
# Control Plane 전용 Machine 관리 : KubeadmControlPlane 리소스 관리, Control Plane 노드 스케일링, etcd 포함 업그레이드 관리
kubectl get providers -n capi-kubeadm-control-plane-system control-plane-kubeadm -o yaml
providerName: kubeadm
type: ControlPlaneProvider
version: v1.12.2
# 실제 인프라 리소스 생성 담당 : 실제 Docker 컨테이너를 VM처럼 생성, Dev/Test 용도 (CAPD)
kubectl get providers -n capd-system infrastructure-docker -o yaml
providerName: docker
type: InfrastructureProvider
version: v1.12.2# 첫 번째 워크로드 구성을 위한 환경 변수 설정 : 필요에 맞게 수정.
## The list of service CIDR, default ["10.128.0.0/12"]
export SERVICE_CIDR=["10.20.0.0/16"]
## The list of pod CIDR, default ["192.168.0.0/16"]
export POD_CIDR=["10.10.0.0/16"]
## The service domain, default "cluster.local"
export SERVICE_DOMAIN="myk8s-1.local"
## PSS Disable
export POD_SECURITY_STANDARD_ENABLED="false"
clusterctl generate cluster capi-quickstart --flavor development \
--kubernetes-version v1.34.3 \
--control-plane-machine-count=3 \
--worker-machine-count=3 \
> capi-quickstart.yaml
# Cluster, Machines, Machine Deployments 등과 같은 Cluster API 객체의 미리 정의된 목록이 포함된 YAML 파일이 생성됨.
open capi-quickstart.yaml
cat capi-quickstart.yaml | grep -E '^apiVersion:|^kind:'
# Apply the workload cluster
kubectl apply -f capi-quickstart.yaml

설치를 진행하면 몇분 기다리다 보면 docker 컨테이너로 여러개가 올라가게 된다. 한개의 컨테이너가 한개의 node 로 생각하면 된다.
클러스터 정보를 확인해 보자
# Accessing the workload cluster
## The cluster will now start provisioning. You can check status with
kubectl get cluster -o wide
NAME CLUSTERCLASS AVAILABLE CP DESIRED CP CURRENT CP READY CP AVAILABLE CP UP-TO-DATE W DESIRED W CURRENT W READY W AVAILABLE W UP-TO-DATE PAUSED PHASE AGE VERSION
capi-quickstart quick-start False 3 3 0 0 3 3 3 0 0 3 False Provisioned 3m38s v1.34.3
## You can also get an “at glance” view of the cluster and its resources by running:
clusterctl describe cluster capi-quickstart
...
# docker 프로바이더에 의해서, 워크로드 클러스터에 머신이 컨테이너로 기동
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d7622e825f15 kindest/node:v1.34.3 "/usr/local/bin/entr…" 2 minutes ago Up 2 minutes 127.0.0.1:32772->6443/tcp capi-quickstart-hvt8l-plmp7
803b5917463f kindest/node:v1.34.3 "/usr/local/bin/entr…" 3 minutes ago Up 3 minutes 127.0.0.1:32771->6443/tcp capi-quickstart-hvt8l-j6tpk
051bcc807657 kindest/node:v1.34.3 "/usr/local/bin/entr…" 3 minutes ago Up 3 minutes capi-quickstart-md-0-64l6n-9hjzs-lcjv4
46b27b6eb154 kindest/node:v1.34.3 "/usr/local/bin/entr…" 3 minutes ago Up 3 minutes capi-quickstart-md-0-64l6n-9hjzs-8rz7j
a5271457c0d6 kindest/node:v1.34.3 "/usr/local/bin/entr…" 3 minutes ago Up 3 minutes capi-quickstart-md-0-64l6n-9hjzs-qnd5z
1607db8af33f kindest/node:v1.34.3 "/usr/local/bin/entr…" 3 minutes ago Up 3 minutes 127.0.0.1:32770->6443/tcp capi-quickstart-hvt8l-lpp75
6c1f5141492c kindest/haproxy:v20230606-42a2262b "haproxy -W -db -f /…" 3 minutes ago Up 3 minutes 0.0.0.0:32768->6443/tcp, 0.0.0.0:32769->8404/tcp capi-quickstart-lb
2f4d7bd4d2ad kindest/node:v1.35.0 "/usr/local/bin/entr…" 22 minutes ago Up 22 minutes 0.0.0.0:30000-30001->30000-30001/tcp, 127.0.0.1:50800->6443/tcp myk8s-control-plane
# 컨트롤 플레인 역할 컨테이너 로그 1대 확인 해보기
docker logs -f capi-quickstart-sn62k-pr4kp
...
Welcome to Debian GNU/Linux 12 (bookworm)!
Queued start job for default target graphical.target.
[ OK ] Created slice kubelet.slic… used to run Kubernetes / Kubelet.
[ OK ] Created slice system-modpr…lice - Slice /system/modprobe.
...
# 워크로드 클러스터 자격증명
clusterctl get kubeconfig capi-quickstart > capi-quickstart.kubeconfig
kubectl --kubeconfig=capi-quickstart.kubeconfig get nodes -owide
# 노드 NotReady 상태 해결 : CNI 플러그인 설치 하자!
kubectl --kubeconfig=capi-quickstart.kubeconfig apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml
kubectl --kubeconfig=capi-quickstart.kubeconfig get nodes -owide
# 워크로드 클러스터 상태 : 성공!
clusterctl describe cluster capi-quickstart성공 결과는 다음과 같다.

구형 맥북이라, docker 를 docker-desktop 으로 사용했는데, docker desktop 은 무조건 localhost 기반으로 통신을 해야 한다고 해서 vi capi-quickstart.kubeconfig 로 실제 환경을 확인하고,
server: https://172.19.0.3:6443
이 부분을 server: https://localhost:55004 로 변경했다.

clusterctl get kubeconfig capi-quickstart > capi-quickstart.kubeconfig
kubectl --kubeconfig=capi-quickstart.kubeconfig get nodes -owide
부분 전에 적용한다.
포트의 경우 docker ps 명령어로 바인딩 된 포트를 사용했다.
# alias 설정 : k8s1
kubectl --kubeconfig=capi-quickstart.kubeconfig cluster-info
alias k8s1='kubectl --kubeconfig=capi-quickstart.kubeconfig'
k8s1 cluster-info
Kubernetes control plane is running at https://192.168.97.3:6443
# kube-ops-view 설치
helm install kube-ops-view geek-cookbook/kube-ops-view --version 1.2.2 \
--set env.TZ="Asia/Seoul" --namespace kube-system --kubeconfig=capi-quickstart.kubeconfig
helm list --kubeconfig=capi-quickstart.kubeconfig -n kube-system
k8s1 get svc,ep -n kube-system kube-ops-view
## kube-ops-view 포트 포워딩 설정
k8s1 -n kube-system port-forward svc/kube-ops-view 8080:8080 &
open "http://127.0.0.1:8080/#scale=1.5" # 웹 접속
# 호스트에서 컨테이너 정보 확인 : LB 컨테이너 1대, CT 컨테이너 3대, WK 컨테이너 3대, 마지막 1대는 최초 kind로 구성한 관리형 k8s
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[Controlplane node] fdf81c4e850a kindest/node:v1.34.3 "/usr/local/bin/entr…" About an hour ago Up About an hour 127.0.0.1:32775->6443/tcp capi-quickstart-j9fdm-6zg8v
[Controlplane node] 6fd07a6a4028 kindest/node:v1.34.3 "/usr/local/bin/entr…" About an hour ago Up About an hour 127.0.0.1:32774->6443/tcp capi-quickstart-j9fdm-27w2s
[Controlplane node] 439466b27b34 kindest/node:v1.34.3 "/usr/local/bin/entr…" About an hour ago Up About an hour capi-quickstart-md-0-p7lv8-t7r9t-nhfpb
[Worker node] 6f700f8ee747 kindest/node:v1.34.3 "/usr/local/bin/entr…" About an hour ago Up About an hour capi-quickstart-md-0-p7lv8-t7r9t-rmcls
[Worker node] 12b85d4f4bab kindest/node:v1.34.3 "/usr/local/bin/entr…" About an hour ago Up About an hour capi-quickstart-md-0-p7lv8-t7r9t-t5ds2
[Worker node] a5507e114f4b kindest/node:v1.34.3 "/usr/local/bin/entr…" About an hour ago Up About an hour 127.0.0.1:32773->6443/tcp capi-quickstart-j9fdm-ggm9z
[CTRL Loadbalancer] d3e002a0c9bc kindest/haproxy:v20230606-42a2262b "haproxy -W -db -f /…" About an hour ago Up About an hour 0.0.0.0:32770->6443/tcp, 0.0.0.0:32771->8404/tcp capi-quickstart-lb
5f01ea7d7bd5 kindest/node:v1.35.0 "/usr/local/bin/entr…" 2 hours ago Up 2 hours 0.0.0.0:30000-30001->30000-30001/tcp, 127.0.0.1:54601->6443/tcp myk8s-control-plane
# 샘플 애플리케이션 배포
cat << EOF | kubectl --kubeconfig=capi-quickstart.kubeconfig apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: webpod
spec:
replicas: 3
selector:
matchLabels:
app: webpod
template:
metadata:
labels:
app: webpod
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- sample-app
topologyKey: "kubernetes.io/hostname"
containers:
- name: webpod
image: traefik/whoami
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: webpod
labels:
app: webpod
spec:
selector:
app: webpod
ports:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 30003
type: NodePort
EOF
# 확인 : alias k8s1='kubectl --kubeconfig=capi-quickstart.kubeconfig'
k8s1 get deploy,pod,svc,ep -owide
# 반복 호출 : 최초 배포한 kind k8s 에 컨트롤 플레인 노드에서 서비스의 NodePort 로 호출
docker ps
CT1=capi-quickstart-hvt8l-hb4hb
docker exec -it myk8s-control-plane curl -s $CT1:30003
while true; do docker exec -it myk8s-control-plane curl -s $CT1:30003 | grep Hostname; date; sleep 1; done
kube-ops-view 를 띄우고 그 다음에 샘플 애플리케이션을 배포해 본다.

kube-ops-view # k8s1 -n kube-system port-forward svc/kube-ops-view 8080:8080 &
haproxy web stats
kubectl --kubeconfig=capi-quickstart.kubeconfig get node -w
watch -d kubectl --kubeconfig=capi-quickstart.kubeconfig get node
watch -d "docker ps ; echo ; clusterctl describe cluster capi-quickstart"모니터링을 하면서 업그레이드를 진행한다.
업그레이드 명령어는 단순하다.
kubectl get cluster
kubectl patch cluster capi-quickstart --type merge -p '{"spec":{"topology":{"version":"v1.35.0"}}}'
## (참고) kube-ops-view 포트 포워딩 exit 될 경우 다시 실행
k8s1 -n kube-system port-forward svc/kube-ops-view 8080:8080 &
# 확인 : 맨 아래 노드는 제거 중
k8s1 get node
# 신규 버전의 머신(컨테이너)이 생성됨을 확인
docker ps
다음과 같이 v1.35 버전의 컨테이너가 추가되면서 업데이트가 진행되는 것을 볼 수 있다.
시간이 조금 소요 되는데, 얼마나 진행되는 지는 알 수 없는 것 같다.

진행이 거의 다 된 모습이고, 마지막 1.34 노드는 제거가 된다.
kubectl patch cluster capi-quickstart --type merge -p '{
"spec": {
"topology": {
"workers": {
"machineDeployments": [
{
"class": "default-worker",
"name": "md-0",
"replicas": 5
}
]
}
}
}
}'
# 노드 확인
k8s1 get nodes 다음과 같이 확장 된 것을 볼 수 있다.

kubectl delete cluster capi-quickstart && docker pskind delete cluster --name myk8s7주간 실습 동안 여러가지 학습을 통해 많은 것을 알게 되었다. 쿠버네티스를 현업에서는 쓰고 있지 않아, 텍스트로만 공부 하였었는데 이번 기회에 실습을 진행하면서 여러가지 cncf 프로젝트 들에 대해서도 알게 되었다.
실습을 완벽하게 이해하고 진행한 것은 아니지만, 새로운 것에 대해 많이 알게 되었고 나중에 추가적으로 학습하여 추후에도 스터디에 참여 해 보고 싶다.
이번 좋은 기회를 주신 가시다님게 감사드립니다.