스터디/K8s Deploy

[K8s Deploy] Bootstrap Kubernetes the hard way

안녕유지 2026. 1. 10. 17:57
Cloudnet K8s Deploy 1주차 스터디를 진행하며 정리한 글입니다.

 

이번 포스팅에서는 Kubernetes의 내부 동작을 보다 깊이 이해하기 위해, 자동화된 설치 도구를 벗어나 Kubernetes the Hard Way 방식으로 클러스터를 구성해 봅니다.

  • CA, TLS 인증서, kubeconfig를 직접 구성하며 Kubernetes 구성 요소 간 mTLS 통신 구조 이해
  • 주요 컴포넌트를 systemd 서비스로 기동하여 실제 운영 환경과 유사한 구조 확인
  • kind Kubernetes와의 비교를 통해 설정 방식과 동작 차이 분석
  • macOS / Windows(WSL2)에서 동일하게 실습 가능한 Vagrant 기반 환경 제공
  • 스크립트 자동화 대신 단계별 명령 실행과 설정 파일 설명 중심으로 실습 진행

 

이번 포스팅에서 구성할 클러스터는 아래와 같습니다.

 

Name Description CPU RAM NIC1 NIC2 Hostname
jumpbox Administration host 2 1536 MB 10.0.2.15 192.168.10.10 jumpbox
server Kubernetes server 2 2GB 10.0.2.15 192.168.10.100 server.kubernetes.local server
node-0 Kubernetes worker 2 2GB 10.0.2.15 192.168.10.101 node-0.kubernetes.local node-0
node-1 Kubernetes worker 2 2GB 10.0.2.15 192.168.10.102 node-1.kubernetes.local node-1

 

실습을 진행한 자료는 아래 Github 내용을 바탕으로 진행하였습니다.

https://github.com/kelseyhightower/kubernetes-the-hard-way

 

GitHub - kelseyhightower/kubernetes-the-hard-way: Bootstrap Kubernetes the hard way. No scripts.

Bootstrap Kubernetes the hard way. No scripts. Contribute to kelseyhightower/kubernetes-the-hard-way development by creating an account on GitHub.

github.com

 

 

기본 환경 설정  (Kind, Jumpbox 세팅)

kind와 krew 플러그인 도구를 설치합니다.

> kind create cluster --name myk8s --image kindest/node:v1.32.8 --config - <<EOF
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
  extraPortMappings:
  - containerPort: 30000
    hostPort: 30000
  - containerPort: 30001
    hostPort: 30001
- role: worker
EOF


> kind get nodes --name myk8s                                                                                                                         13:40:04
myk8s-control-plane
myk8s-worker

> kubens default

 

VirtualBox와 Vagrant를 설치하고, 실습용 가상머신을 배포합니다.

# Vagrantfile , init_cfg.sh 파일 다운로드
> curl -O https://raw.githubusercontent.com/gasida/vagrant-lab/refs/heads/main/k8s-hardway/Vagrantfile
> curl -O https://raw.githubusercontent.com/gasida/vagrant-lab/refs/heads/main/k8s-hardway/init_cfg.sh

# 실습용 가상 머신 배포
> vagrant up

# 실습용 OS 이미지 자동 다운로드 확인
> vagrant box list                                                                                                                                 5m 30s 13:36:01
bento/debian-12    (virtualbox, 202510.26.0, (arm64))
bento/ubuntu-24.04 (virtualbox, 202502.21.0, (arm64))
bento/ubuntu-24.04 (virtualbox, 202508.03.0, (arm64))

# 배포된 가상머신 확인
> vagrant status                                                                                                                                          13:37:31
Current machine states:

jumpbox                   running (virtualbox)
server                    running (virtualbox)
node-0                    running (virtualbox)
node-1                    running (virtualbox)

This environment represents multiple VMs. The VMs are all listed
above with their current state. For more information about a specific
VM, run `vagrant status NAME`.

> vagrant ssh jumpbox                                                                                                                                 13:41:19
Linux jumpbox 6.1.0-40-arm64 #1 SMP Debian 6.1.153-1 (2025-09-20) aarch64

This system is built by the Bento project by Chef Software
More information can be found at https://github.com/chef/bento

Use of this system is acceptance of the OS vendor EULA and License Agreements.

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
root@jumpbox:~#

 

Jumpbox에 필요한 파일들을 설치합니다.

설치 항목 버전
k8s 관련 (kube-apiserver, kubelet 등) 1.32.2
etcd 3.6.0
containerd 2.1.0
runc 1.3.0

 

 

## vagrant 계정 로그인 시 'sudo su -' 실행으로 root 계정 전환됨
> cat /home/vagrant/.bashrc | tail -n 1
sudo su -

> apt-get update && apt install tree git jq yq unzip vim sshpass -y
> pwd
> git clone --depth 1 https://github.com/kelseyhightower/kubernetes-the-hard-way.git
> cd kubernetes-the-hard-way
> tree
.
├── ca.conf
├── configs
│   ├── 10-bridge.conf
│   ├── 99-loopback.conf
│   ├── containerd-config.toml
│   ├── encryption-config.yaml
│   ├── kube-apiserver-to-kubelet.yaml
│   ├── kubelet-config.yaml
│   ├── kube-proxy-config.yaml
│   └── kube-scheduler.yaml
├── CONTRIBUTING.md
├── COPYRIGHT.md
├── docs
│   ├── 01-prerequisites.md
│   ├── 02-jumpbox.md
│   ├── 03-compute-resources.md
│   ├── 04-certificate-authority.md
│   ├── 05-kubernetes-configuration-files.md
│   ├── 06-data-encryption-keys.md
│   ├── 07-bootstrapping-etcd.md
│   ├── 08-bootstrapping-kubernetes-controllers.md
│   ├── 09-bootstrapping-kubernetes-workers.md
│   ├── 10-configuring-kubectl.md
│   ├── 11-pod-network-routes.md
│   ├── 12-smoke-test.md
│   └── 13-cleanup.md
├── downloads-amd64.txt
├── downloads-arm64.txt
├── LICENSE
├── README.md
└── units
    ├── containerd.service
    ├── etcd.service
    ├── kube-apiserver.service
    ├── kube-controller-manager.service
    ├── kubelet.service
    ├── kube-proxy.service
    └── kube-scheduler.service
    

# CPU 아키텍처 확인
> dpkg --print-architecture
arm64

# CPU 아키텍처 별 다운로드 목록 정보 다름
> cat downloads-$(dpkg --print-architecture).txt


# wget 으로 다운로드 실행
> wget -q --show-progress \
  --https-only \
  --timestamping \
  -P downloads \
  -i downloads-$(dpkg --print-architecture).txt

 

 

Computing Resource 프로비저닝

SSH 접속 환경 설정을 구성합니다.

# Machine Database (서버 속성 저장 파일) : IPV4_ADDRESS FQDN HOSTNAME POD_SUBNET
## 참고) server(controlplane)는 kubelet 동작하지 않아서, 파드 네트워크 대역 설정 필요 없음
> cat <<EOF > machines.txt
192.168.10.100 server.kubernetes.local server
192.168.10.101 node-0.kubernetes.local node-0 10.200.0.0/24
192.168.10.102 node-1.kubernetes.local node-1 10.200.1.0/24
EOF

> while read IP FQDN HOST SUBNET; do
  echo "${IP} ${FQDN} ${HOST} ${SUBNET}"
done < machines.txt
192.168.10.100 server.kubernetes.local server
192.168.10.101 node-0.kubernetes.local node-0 10.200.0.0/24
192.168.10.102 node-1.kubernetes.local node-1 10.200.1.0/24



# Configuring SSH Access 설정

# sshd config 설정 파일 확인 : 이미 암호 기반 인증 접속 설정 되어 있음
> grep "^[^#]" /etc/ssh/sshd_config
Include /etc/ssh/sshd_config.d/*.conf
KbdInteractiveAuthentication no
UsePAM yes
X11Forwarding yes
PrintMotd no
AcceptEnv LANG LC_*
Subsystem	sftp	/usr/lib/openssh/sftp-server
UseDNS no
GSSAPIAuthentication no
PasswordAuthentication yes
PermitRootLogin yes

# Generate a new SSH key
> ssh-keygen -t rsa -N "" -f /root/.ssh/id_rsa
Generating public/private rsa key pair.
Your identification has been saved in /root/.ssh/id_rsa
Your public key has been saved in /root/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:fcS3G/41qQLQ94d8DyJFtucYtWin1EOMgBj5pU5lTV8 root@jumpbox
The key's randomart image is:
+---[RSA 3072]----+
|      .+ ..+.o  E|
|      o . +.=.+. |
|       ..= oo*o. |
|       .+o oB.*. |
|       oS o++B+. |
|        ....+=o=.|
|          .. .=+o|
|           .  ..+|
|            ..  .|
+----[SHA256]-----+

> ls -l /root/.ssh
total 8
-rw------- 1 root root 2602 Jan 10 13:51 id_rsa
-rw-r--r-- 1 root root  566 Jan 10 13:51 id_rsa.pub


# Copy the SSH public key to each machine
> while read IP FQDN HOST SUBNET; do
  sshpass -p 'qwe123' ssh-copy-id -o StrictHostKeyChecking=no root@${IP}
done < machines.txt
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh -o 'StrictHostKeyChecking=no' 'root@192.168.10.100'"
and check to make sure that only the key(s) you wanted were added.

/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh -o 'StrictHostKeyChecking=no' 'root@192.168.10.101'"
and check to make sure that only the key(s) you wanted were added.

/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh -o 'StrictHostKeyChecking=no' 'root@192.168.10.102'"
and check to make sure that only the key(s) you wanted were added.


> while read IP FQDN HOST SUBNET; do
  ssh -n root@${IP} cat /root/.ssh/authorized_keys
done < machines.txt
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDzGyBAxcCEBJtrtNhudPuHchrV7a5t7GRWNq4r7ew/KztHsScspWB3tJIeDd4+TQgb5qexNUmwslBqoxYW6Lp8zoGiFJrVoj9GFO1O4iZimnHCIqzhufmkYp/FQuDnEsQi7tPQAjYPTojZfhvgpW4Z09+gPWpyl40P9KVOvGETtocLAdJACcL+I6uq+2JFKG6GnDHbER7zhXYngJKAizj/2t/Dx6l6SC/RfR8Z8jLUBgEguy8RAPQI8k20qYP4ONl77J8/3aQ7XJQptFODfQRmve1KRf8o509AjoDyktOG7LyAFxxlN8RVEDW5gN857WIzjOdnzirAIkt3+6ExrNIyb/XF4JIHWu36HfuAPUusEzIsP6V6+NxbrwQbZvi4wNgCl5OzQFVjtiDlCoa1DzG6rn4onQzW/OgxWoLENe7M4+5w1zS6hGZ/7OW33sO/DeFZOwl6mrdhoXiVBi10+M4sB/CI55a7aQ5J6VcPogxZq6slcoAFrXdiasyJaAPGXjc= 
root@jumpbox
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDzGyBAxcCEBJtrtNhudPuHchrV7a5t7GRWNq4r7ew/KztHsScspWB3tJIeDd4+TQgb5qexNUmwslBqoxYW6Lp8zoGiFJrVoj9GFO1O4iZimnHCIqzhufmkYp/FQuDnEsQi7tPQAjYPTojZfhvgpW4Z09+gPWpyl40P9KVOvGETtocLAdJACcL+I6uq+2JFKG6GnDHbER7zhXYngJKAizj/2t/Dx6l6SC/RfR8Z8jLUBgEguy8RAPQI8k20qYP4ONl77J8/3aQ7XJQptFODfQRmve1KRf8o509AjoDyktOG7LyAFxxlN8RVEDW5gN857WIzjOdnzirAIkt3+6ExrNIyb/XF4JIHWu36HfuAPUusEzIsP6V6+NxbrwQbZvi4wNgCl5OzQFVjtiDlCoa1DzG6rn4onQzW/OgxWoLENe7M4+5w1zS6hGZ/7OW33sO/DeFZOwl6mrdhoXiVBi10+M4sB/CI55a7aQ5J6VcPogxZq6slcoAFrXdiasyJaAPGXjc= 
root@jumpbox
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDzGyBAxcCEBJtrtNhudPuHchrV7a5t7GRWNq4r7ew/KztHsScspWB3tJIeDd4+TQgb5qexNUmwslBqoxYW6Lp8zoGiFJrVoj9GFO1O4iZimnHCIqzhufmkYp/FQuDnEsQi7tPQAjYPTojZfhvgpW4Z09+gPWpyl40P9KVOvGETtocLAdJACcL+I6uq+2JFKG6GnDHbER7zhXYngJKAizj/2t/Dx6l6SC/RfR8Z8jLUBgEguy8RAPQI8k20qYP4ONl77J8/3aQ7XJQptFODfQRmve1KRf8o509AjoDyktOG7LyAFxxlN8RVEDW5gN857WIzjOdnzirAIkt3+6ExrNIyb/XF4JIHWu36HfuAPUusEzIsP6V6+NxbrwQbZvi4wNgCl5OzQFVjtiDlCoa1DzG6rn4onQzW/OgxWoLENe7M4+5w1zS6hGZ/7OW33sO/DeFZOwl6mrdhoXiVBi10+M4sB/CI55a7aQ5J6VcPogxZq6slcoAFrXdiasyJaAPGXjc= 
root@jumpbox


# 아래는 IP 기반으로 접속 확인
> while read IP FQDN HOST SUBNET; do
  ssh -n root@${IP} hostname
done < machines.txt
server
node-0
node-1


> while read IP FQDN HOST SUBNET; do
  ssh -n root@${IP} cat /etc/hosts
done < machines.txt
127.0.0.1	localhost

# The following lines are desirable for IPv6 capable hosts
::1     localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
192.168.10.10  jumpbox
192.168.10.100 server.kubernetes.local server
192.168.10.101 node-0.kubernetes.local node-0
192.168.10.102 node-1.kubernetes.local node-1
127.0.0.1	localhost

# The following lines are desirable for IPv6 capable hosts
::1     localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
192.168.10.10  jumpbox
192.168.10.100 server.kubernetes.local server
192.168.10.101 node-0.kubernetes.local node-0
192.168.10.102 node-1.kubernetes.local node-1
127.0.0.1	localhost

# The following lines are desirable for IPv6 capable hosts
::1     localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
192.168.10.10  jumpbox
192.168.10.100 server.kubernetes.local server
192.168.10.101 node-0.kubernetes.local node-0
192.168.10.102 node-1.kubernetes.local node-1


# Hostnames 설정

> while read IP FQDN HOST SUBNET; do
  ssh -n root@${IP} cat /etc/hosts
done < machines.txt
127.0.0.1	localhost

# The following lines are desirable for IPv6 capable hosts
::1     localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
192.168.10.10  jumpbox
192.168.10.100 server.kubernetes.local server
192.168.10.101 node-0.kubernetes.local node-0
192.168.10.102 node-1.kubernetes.local node-1
127.0.0.1	localhost

# The following lines are desirable for IPv6 capable hosts
::1     localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
192.168.10.10  jumpbox
192.168.10.100 server.kubernetes.local server
192.168.10.101 node-0.kubernetes.local node-0
192.168.10.102 node-1.kubernetes.local node-1
127.0.0.1	localhost

# The following lines are desirable for IPv6 capable hosts
::1     localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
192.168.10.10  jumpbox
192.168.10.100 server.kubernetes.local server
192.168.10.101 node-0.kubernetes.local node-0
192.168.10.102 node-1.kubernetes.local node-1

> while read IP FQDN HOST SUBNET; do
  ssh -n root@${IP} hostname --fqdn
done < machines.txt
server.kubernetes.local
node-0.kubernetes.local
node-1.kubernetes.local

> cat /etc/hosts
while read IP FQDN HOST SUBNET; do
  sshpass -p 'qwe123' ssh -n -o StrictHostKeyChecking=no root@${HOST} hostname
done < machines.txt
127.0.0.1	localhost

# The following lines are desirable for IPv6 capable hosts
::1     localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
192.168.10.10  jumpbox
192.168.10.100 server.kubernetes.local server
192.168.10.101 node-0.kubernetes.local node-0
192.168.10.102 node-1.kubernetes.local node-1
Warning: Permanently added 'server' (ED25519) to the list of known hosts.
server
Warning: Permanently added 'node-0' (ED25519) to the list of known hosts.
node-0
Warning: Permanently added 'node-1' (ED25519) to the list of known hosts.
node-1


> while read IP FQDN HOST SUBNET; do
  sshpass -p 'qwe123' ssh -n root@${HOST} uname -o -m -n
done < machines.txt
server aarch64 GNU/Linux
node-0 aarch64 GNU/Linux
node-1 aarch64 GNU/Linux

 

CA 생성 및 TLS 인증서 발급

Kubernetes 클러스터를 구성하는 각 구성 요소가 mTLS 통신을 하기 위해 어떤 인증서(키·CSR·CRT)를 가지고, 어떤 정체성(CN/O)과 용도로 사용되는지를 정리한 표입니다.

항목 개인키 CSR 인증서 참고 정보 X509v3 Extended Key Usage
Root CA ca.key X ca.crt    
admin admin.key admin.csr admin.crt CN = admin, O = system:masters TLS Web Client Authentication
node-0 node-0.key node-0.csr node-0.crt CN = system:node:node-0, O = system:nodes TLS Web Server / Client Authentication
node-1 node-1.key node-1.csr node-1.crt CN = system:node:node-1, O = system:nodes TLS Web Server / Client Authentication
kube-proxy kube-proxy.key kube-proxy.csr kube-proxy.crt CN = system:kube-proxy, O = system:node-proxier TLS Web Server / Client Authentication
kube-scheduler kube-scheduler.key kube-scheduler kube-scheduler.crt CN = system:kube-scheduler, O = system:kube-scheduler TLS Web Server / Client Authentication
kube-controller-manager kube-controller-manager.key kube-controller-manager.csr kube-controller-manager.crt CN = system:kube-controller-manager, O = system:kube-controller-manager TLS Web Server / Client Authentication
kube-api-server kube-api-server.key kube-api-server.csr kube-api-server.crt CN = kubernetes, SAN: IP(127.0.0.1, 10.32.0.1), DNS(kubernetes,..) TLS Web Server / Client Authentication
service-accounts service-accounts.key service-accounts.csr service-accounts.crt CN = service-accounts TLS Web Client Authentication

 

구성한 네트워크 대역은 다음과 같습니다. 

항목 네트워크 대역 or IP
clusterCIDR 10.200.0.0/16
→ node-0 PodCIDR 10.200.0.0/24
→ node-1 PodCIDR 10.200.1.0/24
ServiceCIDR 10.32.0.0/24
→api clusterIP 10.32.0.1

 

참고를 위해 kind k8s에서 인증서 관련 파일을 확인해보겠습니다.

> docker exec -it myk8s-control-plane sh -c 'apt update && apt install tree yq jq -y'

> docker exec -i myk8s-control-plane kubeadm certs check-expiration                                                                                    5s 06:59:25

[check-expiration] Reading configuration from the "kubeadm-config" ConfigMap in namespace "kube-system"...
[check-expiration] Use 'kubeadm init phase upload-config --config your-config.yaml' to re-upload it.

CERTIFICATE                EXPIRES                  RESIDUAL TIME   CERTIFICATE AUTHORITY   EXTERNALLY MANAGED
admin.conf                 Jan 10, 2027 04:03 UTC   364d            ca                      no
apiserver                  Jan 10, 2027 04:03 UTC   364d            ca                      no
apiserver-etcd-client      Jan 10, 2027 04:03 UTC   364d            etcd-ca                 no
apiserver-kubelet-client   Jan 10, 2027 04:03 UTC   364d            ca                      no
controller-manager.conf    Jan 10, 2027 04:03 UTC   364d            ca                      no
etcd-healthcheck-client    Jan 10, 2027 04:03 UTC   364d            etcd-ca                 no
etcd-peer                  Jan 10, 2027 04:03 UTC   364d            etcd-ca                 no
etcd-server                Jan 10, 2027 04:03 UTC   364d            etcd-ca                 no
front-proxy-client         Jan 10, 2027 04:03 UTC   364d            front-proxy-ca          no
scheduler.conf             Jan 10, 2027 04:03 UTC   364d            ca                      no
super-admin.conf           Jan 10, 2027 04:03 UTC   364d            ca                      no

CERTIFICATE AUTHORITY   EXPIRES                  RESIDUAL TIME   EXTERNALLY MANAGED
ca                      Jan 08, 2036 04:03 UTC   9y              no
etcd-ca                 Jan 08, 2036 04:03 UTC   9y              no
front-proxy-ca          Jan 08, 2036 04:03 UTC   9y              no

> docker exec -it myk8s-control-plane tree /etc/kubernetes                                                                                                06:59:49

/etc/kubernetes
|-- admin.conf
|-- controller-manager.conf
|-- kubelet.conf
|-- manifests
|   |-- etcd.yaml
|   |-- kube-apiserver.yaml
|   |-- kube-controller-manager.yaml
|   `-- kube-scheduler.yaml
|-- pki
|   |-- apiserver-etcd-client.crt
|   |-- apiserver-etcd-client.key
|   |-- apiserver-kubelet-client.crt
|   |-- apiserver-kubelet-client.key
|   |-- apiserver.crt
|   |-- apiserver.key
|   |-- ca.crt
|   |-- ca.key
|   |-- etcd
|   |   |-- ca.crt
|   |   |-- ca.key
|   |   |-- healthcheck-client.crt
|   |   |-- healthcheck-client.key
|   |   |-- peer.crt
|   |   |-- peer.key
|   |   |-- server.crt
|   |   `-- server.key
|   |-- front-proxy-ca.crt
|   |-- front-proxy-ca.key
|   |-- front-proxy-client.crt
|   |-- front-proxy-client.key
|   |-- sa.key
|   `-- sa.pub
|-- scheduler.conf
`-- super-admin.conf

4 directories, 31 files

 

CA 설정파일, certificate, private key를 생성하겠습니다.

 

우선 certificate authority를 생성하겠습니다.

CN(Common Name)은 X.509 인증서의 식별자 이름 필드로 인증서 주체(또는 발급자)를 사람이 알아보기 쉽게 부르는 이름입니다.

Issuer는 이 인증서를 발급한 CA의 DN, Subject는 이 인증서의 소유자 DN입니다.

따라서, 현재 이 인증서는 self-signed CA으로, Issuer와 Subject가 CN=CA입니다.

root@jumpbox:~/kubernetes-the-hard-way# openssl genrsa -out ca.key 4096
root@jumpbox:~/kubernetes-the-hard-way# ls -l ca.key
-rw------- 1 root root 3272 Jan 11 07:04 ca.key
root@jumpbox:~/kubernetes-the-hard-way# cat ca.key
-----BEGIN PRIVATE KEY-----
MIIJRAIBADANBgkqhkiG9w0BAQEFAASCCS4wggkqAgEAAoICAQCe03U+G0LIGAZd
GlXG5uInPOFL35RAls8fXKDFjeT1R4F+BZX8mVDR9kxuijGKzZzkAY+4nNiahOcW
Z/eoSBRw5CwVRtIUiRFJA0CgjZ1O8wMgQrnH77GTqrtieJcZdAPu3AAY3uCi2THr
cUfQ6UEygoAY0+rQx2oXQRmsqq7JMJllI6sOxyTqj7amUjl542HlzQSIAQ2Vi1b1
BbLOsLxUr1xcYcJJePOFOw0kAXqQWjlpMx+YXsLEAtOMlCKwnhUljD4a5N0pqDQz
igr8y3Ykt6kgjGLG348wkXmArGNS3lPZrzN+7osFP08rtN3a6C4sYU7y60Fo4Tw4
Jhzp/SCWpG12sYgDO68Do4p9FfSA8JzGjrtBM/Iu0JkQR5nKha+ERJBQudzcfk+x
b3TbCi0Tj8n8bbTvx3pdODhXn+lLxPjj0KbZ7C5bKjoyxBjZhWYYfDSovwuCAIP0
xOq8DWFg+zyPjrqpFZuwyDnWEWVaTrKg7kT8fnBQecFP4u5Wi2L2lDj+FnzuHoyw
KU7IL6UTcUjZj9ICmN9YoX224iHF9yvC6emu74v51X3HrLOf0j+oHxm9orLWcofo
Q3AOc7uJ7sX7nWChpmrQRZ74fHmDYSm7R8/688674rTKYsGJdpNsAoJIyijhlmil
AHQAxSSiyzofVzpEXnCXpmViTLD5kQIDAQABAoICACOJnQowf1jWR1Y9tkOzFZdC
AAdCF6H8HIwf5blObpSTU14nUdAbXgIc4i05rqwoJZq+3rGoJq8sXaidysRUnH5G
D7cTCZ6erMdxetxx02j+5wwo4fjioRExeowl/2kqlFa10y+9bvYBMzJDPpZ4GqZ6
nL7xa/EbLZnWbzA7YLCTtz7yJCxCUvhI/81nSIUFY7pPjVwBIFD9xI8+nyuwT/OC
6V+iYB6geZyuAdq0mgACsCXh0of9bAb/uuYRn1F1jbXBE4RhATt473U4xgyaWe0N
S0KFJvTowNlVM6Ke7/py1MA4e4VDSsf5ynU1Gw8INIypmUixawlUnGzT2lRg1xGD
o6Jjec5usxBLEDoW81NB/IHicn0RxLMnlGwhI4fn2qvOEmIs9j7QkvISNSxUX5+I
/6hE8EQq7SYQcj1BgnkT2vuyEGoBLAnV3PbWfwC89P4+a4ZtsV/7sK66hgTl4c9P
y5B5/oPt6pxYF2T2XeDkP6Szj77hnDCFovfcClqrOPDB9s4HRUTpszdMSykTpjoG
z+9z7JWSTHd/IAaF7wK/3HGfUIfHEh6EV7+jokxdYG3ixswTcqkaplN8tqtJdPKw
Q4wSmBkNfckpTtoWyi47a5GaENg/wDGgGKyyWLPOIQdXxHUTcAIUcY0eUl9cWNCa
hNR7ZqFWyxC6jCN6cSOBAoIBAQDPTqwANmqVlJ93B+OGVKKaJ4ao+nJHSFXR3fN/
nSC8i2gphIlcQS42GsHz4OAYwR+Q1nAX1f5hUmOwdj2TRQsgKBfYSrb4vjjjVK6v
xbPGLC5gn+TJA9J8kt8JelFa4GoOvOBJ/GBhrQwK3gRtaeLtj92io2ab90XbrvXZ
bvVfGc+9zPEzgS3I0WdQDTvWome4avOpP30ULQqVay2XkLl2slO/q7cs0mRhHEV4
H+gp4mswbmUwiW1IFThYCDvOuE4ir3A+WZKyOhTJjF2nsnHGiaMB0RhUa3cC6O1N
DgJDBHlX1EVxINF3z1DnduPTVpv3qL/jq9yn+GGfynCYQvQNAoIBAQDEIZ6TN91+
Rfu9VI+ozwkfBDIW1nbc/Y8KDQd0nWVK14LiPDyxZdhXQm+97jouzcmq45rHr5QM
nCfwo45SeitOA8f4tQewbz5Q1V9td3kOUHva4wf0f0bSAEQLPiYOJPn35pxRMNfH
XuRg1lqMVHGdvVoS/ZR24TEh2fjZjhEMqMAir14QUN8313qTqVziK6Hbm7qJxDcM
RcGf18edtVlV5D/kyucCGSeRUjdJodLB+nCw22i/RvCLhdp2nFXsp67Jmt45Gz7m
YlX3ZM5oU1dWTKELJ8QGutAcphI+P6QhvKlUlO3Xee4+YOC9PWXezsc43hCJ2Qqa
ddhavH9YuyaVAoIBAQCBH0taxooUqQG6Lhu1a7nrsnrZfUT4yUFK+qfT8JaXWW2D
jp3P7HlQEdKEiKiMQp3apPYkopFTJPIa00r/E54eZVqUydS1kiX00qYLrWSQJqys
WmsyGUNdfE2XpaxOokDs9Q/uhVey/wnlKuwvCijiNx2hU41xz86fSpau28HRfk46
tg/2OJu/3U4wOk3vHjDkWRlzbawGiRdygdNf+DDMkb5AQEBTlqgXJHjQnW8Jx5Fk
FR7J4I9EupLhoh8+XuWsDQIok7ofcLXJ47fh3++l7cyuMQKqclUqZtKHkBYwj/TU
k8686+gMbADEavT0iZmT5HPA5ycFKFwGHx2KeQlxAoIBAQChZrlElXik7ZqY1/nR
BW+QIrfFq3/tpIwNzWMRSGWPDYMcAk4//nvmcznZpy4iTh9jjiJVqdu/9NG5ah85
KGhyrxHlTbSiMSmrA6ygPO1WJk2Gd8aYIhV5w9Y7Gk3e3fcHVrPU7MjlvOVb+4pQ
aT2GfcieUCfZHMB+Bw6OmibVsBlNcduKucK4BY9N7NYPGbD9NE5yCRLz+oO4sq4G
zrJRyJ/7/C3WwDSblnkBEzaJgzsxj53Hqu1RJDn/2e+r7OId7mBpxk4g8VOlX0Os
/siksDLnJzZeA2Y37UKeD2lWihcfD+AarrCsjLTlhp1KmgfAeJ5Lklzzd38wTGbP
8lNxAoIBAQCNikVjxJ7XChzch3b6rIcDM3cfL7Et7XDKXMJa/Q9HQy1Lm2tgFVJA
YmHaFpNiq9CVRmyZ6pxpXMEDjClifdpi1utl8LHanDvJRHtKxi0d5oogl4E2wnD7
uVxZu7pX7KjsQSan0YV9Z4/DoW0gKBljoVOxOsUMwrevCN9jJjelo2vyP3bT6F0V
jtxleALdKGcvFL0sSRk3BFQzS6SOgl/7V5CpWvxq7axgArvCabfAG9MAvLMuuXMQ
sRRJ87cgboc7i6nutfldMhWeXM1kFJgvnOwTu8mBEHLOGTkUKewkAgT2EdafIkCK
nCdtHCf+g7W4SvE216mOC6MjpU+IP/+S
-----END PRIVATE KEY-----
root@jumpbox:~/kubernetes-the-hard-way#
root@jumpbox:~/kubernetes-the-hard-way# openssl rsa -in ca.key -text -noout # 개인키 구조 확인
Private-Key: (4096 bit, 2 primes)
modulus:
    00:9e:d3:75:3e:1b:42:c8:18:06:5d:1a:55:c6:e6:
    e2:27:3c:e1:4b:df:94:40:96:cf:1f:5c:a0:c5:8d:
    e4:f5:47:81:7e:05:95:fc:99:50:d1:f6:4c:6e:8a:
    31:8a:cd:9c:e4:01:8f:b8:9c:d8:9a:84:e7:16:67:
    f7:a8:48:14:70:e4:2c:15:46:d2:14:89:11:49:03:
    40:a0:8d:9d:4e:f3:03:20:42:b9:c7:ef:b1:93:aa:
    bb:62:78:97:19:74:03:ee:dc:00:18:de:e0:a2:d9:
    31:eb:71:47:d0:e9:41:32:82:80:18:d3:ea:d0:c7:
    6a:17:41:19:ac:aa:ae:c9:30:99:65:23:ab:0e:c7:
    24:ea:8f:b6:a6:52:39:79:e3:61:e5:cd:04:88:01:
    0d:95:8b:56:f5:05:b2:ce:b0:bc:54:af:5c:5c:61:
    c2:49:78:f3:85:3b:0d:24:01:7a:90:5a:39:69:33:
    1f:98:5e:c2:c4:02:d3:8c:94:22:b0:9e:15:25:8c:
    3e:1a:e4:dd:29:a8:34:33:8a:0a:fc:cb:76:24:b7:
    a9:20:8c:62:c6:df:8f:30:91:79:80:ac:63:52:de:
    53:d9:af:33:7e:ee:8b:05:3f:4f:2b:b4:dd:da:e8:
    2e:2c:61:4e:f2:eb:41:68:e1:3c:38:26:1c:e9:fd:
    20:96:a4:6d:76:b1:88:03:3b:af:03:a3:8a:7d:15:
    f4:80:f0:9c:c6:8e:bb:41:33:f2:2e:d0:99:10:47:
    99:ca:85:af:84:44:90:50:b9:dc:dc:7e:4f:b1:6f:
    74:db:0a:2d:13:8f:c9:fc:6d:b4:ef:c7:7a:5d:38:
    38:57:9f:e9:4b:c4:f8:e3:d0:a6:d9:ec:2e:5b:2a:
    3a:32:c4:18:d9:85:66:18:7c:34:a8:bf:0b:82:00:
    83:f4:c4:ea:bc:0d:61:60:fb:3c:8f:8e:ba:a9:15:
    9b:b0:c8:39:d6:11:65:5a:4e:b2:a0:ee:44:fc:7e:
    70:50:79:c1:4f:e2:ee:56:8b:62:f6:94:38:fe:16:
    7c:ee:1e:8c:b0:29:4e:c8:2f:a5:13:71:48:d9:8f:
    d2:02:98:df:58:a1:7d:b6:e2:21:c5:f7:2b:c2:e9:
    e9:ae:ef:8b:f9:d5:7d:c7:ac:b3:9f:d2:3f:a8:1f:
    19:bd:a2:b2:d6:72:87:e8:43:70:0e:73:bb:89:ee:
    c5:fb:9d:60:a1:a6:6a:d0:45:9e:f8:7c:79:83:61:
    29:bb:47:cf:fa:f3:ce:bb:e2:b4:ca:62:c1:89:76:
    93:6c:02:82:48:ca:28:e1:96:68:a5:00:74:00:c5:
    24:a2:cb:3a:1f:57:3a:44:5e:70:97:a6:65:62:4c:
    b0:f9:91
publicExponent: 65537 (0x10001)
privateExponent:
    23:89:9d:0a:30:7f:58:d6:47:56:3d:b6:43:b3:15:
    97:42:00:07:42:17:a1:fc:1c:8c:1f:e5:b9:4e:6e:
    94:93:53:5e:27:51:d0:1b:5e:02:1c:e2:2d:39:ae:
    ac:28:25:9a:be:de:b1:a8:26:af:2c:5d:a8:9d:ca:
    c4:54:9c:7e:46:0f:b7:13:09:9e:9e:ac:c7:71:7a:
    dc:71:d3:68:fe:e7:0c:28:e1:f8:e2:a1:11:31:7a:
    8c:25:ff:69:2a:94:56:b5:d3:2f:bd:6e:f6:01:33:
    32:43:3e:96:78:1a:a6:7a:9c:be:f1:6b:f1:1b:2d:
    99:d6:6f:30:3b:60:b0:93:b7:3e:f2:24:2c:42:52:
    f8:48:ff:cd:67:48:85:05:63:ba:4f:8d:5c:01:20:
    50:fd:c4:8f:3e:9f:2b:b0:4f:f3:82:e9:5f:a2:60:
    1e:a0:79:9c:ae:01:da:b4:9a:00:02:b0:25:e1:d2:
    87:fd:6c:06:ff:ba:e6:11:9f:51:75:8d:b5:c1:13:
    84:61:01:3b:78:ef:75:38:c6:0c:9a:59:ed:0d:4b:
    42:85:26:f4:e8:c0:d9:55:33:a2:9e:ef:fa:72:d4:
    c0:38:7b:85:43:4a:c7:f9:ca:75:35:1b:0f:08:34:
    8c:a9:99:48:b1:6b:09:54:9c:6c:d3:da:54:60:d7:
    11:83:a3:a2:63:79:ce:6e:b3:10:4b:10:3a:16:f3:
    53:41:fc:81:e2:72:7d:11:c4:b3:27:94:6c:21:23:
    87:e7:da:ab:ce:12:62:2c:f6:3e:d0:92:f2:12:35:
    2c:54:5f:9f:88:ff:a8:44:f0:44:2a:ed:26:10:72:
    3d:41:82:79:13:da:fb:b2:10:6a:01:2c:09:d5:dc:
    f6:d6:7f:00:bc:f4:fe:3e:6b:86:6d:b1:5f:fb:b0:
    ae:ba:86:04:e5:e1:cf:4f:cb:90:79:fe:83:ed:ea:
    9c:58:17:64:f6:5d:e0:e4:3f:a4:b3:8f:be:e1:9c:
    30:85:a2:f7:dc:0a:5a:ab:38:f0:c1:f6:ce:07:45:
    44:e9:b3:37:4c:4b:29:13:a6:3a:06:cf:ef:73:ec:
    95:92:4c:77:7f:20:06:85:ef:02:bf:dc:71:9f:50:
    87:c7:12:1e:84:57:bf:a3:a2:4c:5d:60:6d:e2:c6:
    cc:13:72:a9:1a:a6:53:7c:b6:ab:49:74:f2:b0:43:
    8c:12:98:19:0d:7d:c9:29:4e:da:16:ca:2e:3b:6b:
    91:9a:10:d8:3f:c0:31:a0:18:ac:b2:58:b3:ce:21:
    07:57:c4:75:13:70:02:14:71:8d:1e:52:5f:5c:58:
    d0:9a:84:d4:7b:66:a1:56:cb:10:ba:8c:23:7a:71:
    23:81
prime1:
    00:cf:4e:ac:00:36:6a:95:94:9f:77:07:e3:86:54:
    a2:9a:27:86:a8:fa:72:47:48:55:d1:dd:f3:7f:9d:
    20:bc:8b:68:29:84:89:5c:41:2e:36:1a:c1:f3:e0:
    e0:18:c1:1f:90:d6:70:17:d5:fe:61:52:63:b0:76:
    3d:93:45:0b:20:28:17:d8:4a:b6:f8:be:38:e3:54:
    ae:af:c5:b3:c6:2c:2e:60:9f:e4:c9:03:d2:7c:92:
    df:09:7a:51:5a:e0:6a:0e:bc:e0:49:fc:60:61:ad:
    0c:0a:de:04:6d:69:e2:ed:8f:dd:a2:a3:66:9b:f7:
    45:db:ae:f5:d9:6e:f5:5f:19:cf:bd:cc:f1:33:81:
    2d:c8:d1:67:50:0d:3b:d6:a2:67:b8:6a:f3:a9:3f:
    7d:14:2d:0a:95:6b:2d:97:90:b9:76:b2:53:bf:ab:
    b7:2c:d2:64:61:1c:45:78:1f:e8:29:e2:6b:30:6e:
    65:30:89:6d:48:15:38:58:08:3b:ce:b8:4e:22:af:
    70:3e:59:92:b2:3a:14:c9:8c:5d:a7:b2:71:c6:89:
    a3:01:d1:18:54:6b:77:02:e8:ed:4d:0e:02:43:04:
    79:57:d4:45:71:20:d1:77:cf:50:e7:76:e3:d3:56:
    9b:f7:a8:bf:e3:ab:dc:a7:f8:61:9f:ca:70:98:42:
    f4:0d
prime2:
    00:c4:21:9e:93:37:dd:7e:45:fb:bd:54:8f:a8:cf:
    09:1f:04:32:16:d6:76:dc:fd:8f:0a:0d:07:74:9d:
    65:4a:d7:82:e2:3c:3c:b1:65:d8:57:42:6f:bd:ee:
    3a:2e:cd:c9:aa:e3:9a:c7:af:94:0c:9c:27:f0:a3:
    8e:52:7a:2b:4e:03:c7:f8:b5:07:b0:6f:3e:50:d5:
    5f:6d:77:79:0e:50:7b:da:e3:07:f4:7f:46:d2:00:
    44:0b:3e:26:0e:24:f9:f7:e6:9c:51:30:d7:c7:5e:
    e4:60:d6:5a:8c:54:71:9d:bd:5a:12:fd:94:76:e1:
    31:21:d9:f8:d9:8e:11:0c:a8:c0:22:af:5e:10:50:
    df:37:d7:7a:93:a9:5c:e2:2b:a1:db:9b:ba:89:c4:
    37:0c:45:c1:9f:d7:c7:9d:b5:59:55:e4:3f:e4:ca:
    e7:02:19:27:91:52:37:49:a1:d2:c1:fa:70:b0:db:
    68:bf:46:f0:8b:85:da:76:9c:55:ec:a7:ae:c9:9a:
    de:39:1b:3e:e6:62:55:f7:64:ce:68:53:57:56:4c:
    a1:0b:27:c4:06:ba:d0:1c:a6:12:3e:3f:a4:21:bc:
    a9:54:94:ed:d7:79:ee:3e:60:e0:bd:3d:65:de:ce:
    c7:38:de:10:89:d9:0a:9a:75:d8:5a:bc:7f:58:bb:
    26:95
exponent1:
    00:81:1f:4b:5a:c6:8a:14:a9:01:ba:2e:1b:b5:6b:
    b9:eb:b2:7a:d9:7d:44:f8:c9:41:4a:fa:a7:d3:f0:
    96:97:59:6d:83:8e:9d:cf:ec:79:50:11:d2:84:88:
    a8:8c:42:9d:da:a4:f6:24:a2:91:53:24:f2:1a:d3:
    4a:ff:13:9e:1e:65:5a:94:c9:d4:b5:92:25:f4:d2:
    a6:0b:ad:64:90:26:ac:ac:5a:6b:32:19:43:5d:7c:
    4d:97:a5:ac:4e:a2:40:ec:f5:0f:ee:85:57:b2:ff:
    09:e5:2a:ec:2f:0a:28:e2:37:1d:a1:53:8d:71:cf:
    ce:9f:4a:96:ae:db:c1:d1:7e:4e:3a:b6:0f:f6:38:
    9b:bf:dd:4e:30:3a:4d:ef:1e:30:e4:59:19:73:6d:
    ac:06:89:17:72:81:d3:5f:f8:30:cc:91:be:40:40:
    40:53:96:a8:17:24:78:d0:9d:6f:09:c7:91:64:15:
    1e:c9:e0:8f:44:ba:92:e1:a2:1f:3e:5e:e5:ac:0d:
    02:28:93:ba:1f:70:b5:c9:e3:b7:e1:df:ef:a5:ed:
    cc:ae:31:02:aa:72:55:2a:66:d2:87:90:16:30:8f:
    f4:d4:93:ce:bc:eb:e8:0c:6c:00:c4:6a:f4:f4:89:
    99:93:e4:73:c0:e7:27:05:28:5c:06:1f:1d:8a:79:
    09:71
exponent2:
    00:a1:66:b9:44:95:78:a4:ed:9a:98:d7:f9:d1:05:
    6f:90:22:b7:c5:ab:7f:ed:a4:8c:0d:cd:63:11:48:
    65:8f:0d:83:1c:02:4e:3f:fe:7b:e6:73:39:d9:a7:
    2e:22:4e:1f:63:8e:22:55:a9:db:bf:f4:d1:b9:6a:
    1f:39:28:68:72:af:11:e5:4d:b4:a2:31:29:ab:03:
    ac:a0:3c:ed:56:26:4d:86:77:c6:98:22:15:79:c3:
    d6:3b:1a:4d:de:dd:f7:07:56:b3:d4:ec:c8:e5:bc:
    e5:5b:fb:8a:50:69:3d:86:7d:c8:9e:50:27:d9:1c:
    c0:7e:07:0e:8e:9a:26:d5:b0:19:4d:71:db:8a:b9:
    c2:b8:05:8f:4d:ec:d6:0f:19:b0:fd:34:4e:72:09:
    12:f3:fa:83:b8:b2:ae:06:ce:b2:51:c8:9f:fb:fc:
    2d:d6:c0:34:9b:96:79:01:13:36:89:83:3b:31:8f:
    9d:c7:aa:ed:51:24:39:ff:d9:ef:ab:ec:e2:1d:ee:
    60:69:c6:4e:20:f1:53:a5:5f:43:ac:fe:c8:a4:b0:
    32:e7:27:36:5e:03:66:37:ed:42:9e:0f:69:56:8a:
    17:1f:0f:e0:1a:ae:b0:ac:8c:b4:e5:86:9d:4a:9a:
    07:c0:78:9e:4b:92:5c:f3:77:7f:30:4c:66:cf:f2:
    53:71
coefficient:
    00:8d:8a:45:63:c4:9e:d7:0a:1c:dc:87:76:fa:ac:
    87:03:33:77:1f:2f:b1:2d:ed:70:ca:5c:c2:5a:fd:
    0f:47:43:2d:4b:9b:6b:60:15:52:40:62:61:da:16:
    93:62:ab:d0:95:46:6c:99:ea:9c:69:5c:c1:03:8c:
    29:62:7d:da:62:d6:eb:65:f0:b1:da:9c:3b:c9:44:
    7b:4a:c6:2d:1d:e6:8a:20:97:81:36:c2:70:fb:b9:
    5c:59:bb:ba:57:ec:a8:ec:41:26:a7:d1:85:7d:67:
    8f:c3:a1:6d:20:28:19:63:a1:53:b1:3a:c5:0c:c2:
    b7:af:08:df:63:26:37:a5:a3:6b:f2:3f:76:d3:e8:
    5d:15:8e:dc:65:78:02:dd:28:67:2f:14:bd:2c:49:
    19:37:04:54:33:4b:a4:8e:82:5f:fb:57:90:a9:5a:
    fc:6a:ed:ac:60:02:bb:c2:69:b7:c0:1b:d3:00:bc:
    b3:2e:b9:73:10:b1:14:49:f3:b7:20:6e:87:3b:8b:
    a9:ee:b5:f9:5d:32:15:9e:5c:cd:64:14:98:2f:9c:
    ec:13:bb:c9:81:10:72:ce:19:39:14:29:ec:24:02:
    04:f6:11:d6:9f:22:40:8a:9c:27:6d:1c:27:fe:83:
    b5:b8:4a:f1:36:d7:a9:8e:0b:a3:23:a5:4f:88:3f:
    ff:92
    
    
# Root CA 인증서 생성 : ca.crt
## -x509 : CSR을 만들지 않고 바로 인증서(X.509) 생성, 즉, Self-Signed Certificate
## -noenc : 개인키를 암호화하지 않음, 즉, CA 키(ca.key)에 패스프레이즈 없음
## -config ca.conf : 인증서 세부 정보는 설정 파일에서 읽음 , [req] 섹션 사용됨 - DN 정보 → [req_distinguished_name] , CA 확장 → [ca_x509_extensions]
root@jumpbox:~/kubernetes-the-hard-way# openssl req -x509 -new -sha512 -noenc \
  -key ca.key -days 3653 \
  -config ca.conf \
  -out ca.crt
root@jumpbox:~/kubernetes-the-hard-way# ls -l ca.crt
-rw-r--r-- 1 root root 1899 Jan 11 07:05 ca.crt


# ca.conf 내용 확인
root@jumpbox:~/kubernetes-the-hard-way# cat ca.conf
[req]
distinguished_name = req_distinguished_name
prompt             = no
x509_extensions    = ca_x509_extensions

[ca_x509_extensions]
basicConstraints = CA:TRUE # 이 인증서는 CA 역할 가능
keyUsage         = cRLSign, keyCertSign # cRLSign: 인증서 폐기 목록(CRL) 서명 가능, keyCertSign: 다른 인증서를 서명할 수 있음

[req_distinguished_name]
C   = US
ST  = Washington
L   = Seattle
CN  = CA

[admin]
distinguished_name = admin_distinguished_name
prompt             = no
req_extensions     = default_req_extensions

[admin_distinguished_name]
CN = admin
O  = system:masters

# Service Accounts
#
# The Kubernetes Controller Manager leverages a key pair to generate
# and sign service account tokens as described in the
# [managing service accounts](https://kubernetes.io/docs/admin/service-accounts-admin/)
# documentation.

[service-accounts]
distinguished_name = service-accounts_distinguished_name
prompt             = no
req_extensions     = default_req_extensions

[service-accounts_distinguished_name]
CN = service-accounts

# Worker Nodes
#
# Kubernetes uses a [special-purpose authorization mode](https://kubernetes.io/docs/admin/authorization/node/)
# called Node Authorizer, that specifically authorizes API requests made
# by [Kubelets](https://kubernetes.io/docs/concepts/overview/components/#kubelet).
# In order to be authorized by the Node Authorizer, Kubelets must use a credential
# that identifies them as being in the `system:nodes` group, with a username
# of `system:node:<nodeName>`.

[node-0]
distinguished_name = node-0_distinguished_name
prompt             = no
req_extensions     = node-0_req_extensions

[node-0_req_extensions]
basicConstraints     = CA:FALSE
extendedKeyUsage     = clientAuth, serverAuth
keyUsage             = critical, digitalSignature, keyEncipherment
nsCertType           = client
nsComment            = "Node-0 Certificate"
subjectAltName       = DNS:node-0, IP:127.0.0.1
subjectKeyIdentifier = hash

[node-0_distinguished_name]
CN = system:node:node-0
O  = system:nodes
C  = US
ST = Washington
L  = Seattle

[node-1]
distinguished_name = node-1_distinguished_name
prompt             = no
req_extensions     = node-1_req_extensions

[node-1_req_extensions]
basicConstraints     = CA:FALSE
extendedKeyUsage     = clientAuth, serverAuth
keyUsage             = critical, digitalSignature, keyEncipherment
nsCertType           = client
nsComment            = "Node-1 Certificate"
subjectAltName       = DNS:node-1, IP:127.0.0.1
subjectKeyIdentifier = hash

[node-1_distinguished_name]
CN = system:node:node-1
O  = system:nodes
C  = US
ST = Washington
L  = Seattle


# Kube Proxy Section
[kube-proxy]
distinguished_name = kube-proxy_distinguished_name
prompt             = no
req_extensions     = kube-proxy_req_extensions

[kube-proxy_req_extensions]
basicConstraints     = CA:FALSE
extendedKeyUsage     = clientAuth, serverAuth
keyUsage             = critical, digitalSignature, keyEncipherment
nsCertType           = client
nsComment            = "Kube Proxy Certificate"
subjectAltName       = DNS:kube-proxy, IP:127.0.0.1
subjectKeyIdentifier = hash

[kube-proxy_distinguished_name]
CN = system:kube-proxy
O  = system:node-proxier
C  = US
ST = Washington
L  = Seattle


# Controller Manager
[kube-controller-manager]
distinguished_name = kube-controller-manager_distinguished_name
prompt             = no
req_extensions     = kube-controller-manager_req_extensions

[kube-controller-manager_req_extensions]
basicConstraints     = CA:FALSE
extendedKeyUsage     = clientAuth, serverAuth
keyUsage             = critical, digitalSignature, keyEncipherment
nsCertType           = client
nsComment            = "Kube Controller Manager Certificate"
subjectAltName       = DNS:kube-controller-manager, IP:127.0.0.1
subjectKeyIdentifier = hash

[kube-controller-manager_distinguished_name]
CN = system:kube-controller-manager
O  = system:kube-controller-manager
C  = US
ST = Washington
L  = Seattle


# Scheduler
[kube-scheduler]
distinguished_name = kube-scheduler_distinguished_name
prompt             = no
req_extensions     = kube-scheduler_req_extensions

[kube-scheduler_req_extensions]
basicConstraints     = CA:FALSE
extendedKeyUsage     = clientAuth, serverAuth
keyUsage             = critical, digitalSignature, keyEncipherment
nsCertType           = client
nsComment            = "Kube Scheduler Certificate"
subjectAltName       = DNS:kube-scheduler, IP:127.0.0.1
subjectKeyIdentifier = hash

[kube-scheduler_distinguished_name]
CN = system:kube-scheduler
O  = system:system:kube-scheduler
C  = US
ST = Washington
L  = Seattle


# API Server
#
# The Kubernetes API server is automatically assigned the `kubernetes`
# internal dns name, which will be linked to the first IP address (`10.32.0.1`)
# from the address range (`10.32.0.0/24`) reserved for internal cluster
# services.

[kube-api-server]
distinguished_name = kube-api-server_distinguished_name
prompt             = no
req_extensions     = kube-api-server_req_extensions

[kube-api-server_req_extensions]
basicConstraints     = CA:FALSE
extendedKeyUsage     = clientAuth, serverAuth
keyUsage             = critical, digitalSignature, keyEncipherment
nsCertType           = client, server
nsComment            = "Kube API Server Certificate"
subjectAltName       = @kube-api-server_alt_names
subjectKeyIdentifier = hash

[kube-api-server_alt_names]
IP.0  = 127.0.0.1
IP.1  = 10.32.0.1
DNS.0 = kubernetes
DNS.1 = kubernetes.default
DNS.2 = kubernetes.default.svc
DNS.3 = kubernetes.default.svc.cluster
DNS.4 = kubernetes.svc.cluster.local
DNS.5 = server.kubernetes.local
DNS.6 = api-server.kubernetes.local

[kube-api-server_distinguished_name]
CN = kubernetes
C  = US
ST = Washington
L  = Seattle


[default_req_extensions]
basicConstraints     = CA:FALSE
extendedKeyUsage     = clientAuth
keyUsage             = critical, digitalSignature, keyEncipherment
nsCertType           = client
nsComment            = "Admin Client Certificate"
subjectKeyIdentifier = hash



root@jumpbox:~/kubernetes-the-hard-way# cat ca.crt
-----BEGIN CERTIFICATE-----
MIIFTDCCAzSgAwIBAgIUcSMTtyKoWqyd+YXYFjUVawNiOjkwDQYJKoZIhvcNAQEN
BQAwQTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcM
B1NlYXR0bGUxCzAJBgNVBAMMAkNBMB4XDTI2MDExMDIyMDU1NloXDTM2MDExMTIy
MDU1NlowQTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNV
BAcMB1NlYXR0bGUxCzAJBgNVBAMMAkNBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
MIICCgKCAgEAntN1PhtCyBgGXRpVxubiJzzhS9+UQJbPH1ygxY3k9UeBfgWV/JlQ
0fZMbooxis2c5AGPuJzYmoTnFmf3qEgUcOQsFUbSFIkRSQNAoI2dTvMDIEK5x++x
k6q7YniXGXQD7twAGN7gotkx63FH0OlBMoKAGNPq0MdqF0EZrKquyTCZZSOrDsck
6o+2plI5eeNh5c0EiAENlYtW9QWyzrC8VK9cXGHCSXjzhTsNJAF6kFo5aTMfmF7C
xALTjJQisJ4VJYw+GuTdKag0M4oK/Mt2JLepIIxixt+PMJF5gKxjUt5T2a8zfu6L
BT9PK7Td2uguLGFO8utBaOE8OCYc6f0glqRtdrGIAzuvA6OKfRX0gPCcxo67QTPy
LtCZEEeZyoWvhESQULnc3H5PsW902wotE4/J/G2078d6XTg4V5/pS8T449Cm2ewu
Wyo6MsQY2YVmGHw0qL8LggCD9MTqvA1hYPs8j466qRWbsMg51hFlWk6yoO5E/H5w
UHnBT+LuVoti9pQ4/hZ87h6MsClOyC+lE3FI2Y/SApjfWKF9tuIhxfcrwunpru+L
+dV9x6yzn9I/qB8ZvaKy1nKH6ENwDnO7ie7F+51goaZq0EWe+Hx5g2Epu0fP+vPO
u+K0ymLBiXaTbAKCSMoo4ZZopQB0AMUkoss6H1c6RF5wl6ZlYkyw+ZECAwEAAaM8
MDowDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFJ7NNroia0On
2yMpl1Mb0XLfbWHSMA0GCSqGSIb3DQEBDQUAA4ICAQBwpr8+8niGE9UjAKQG2ANk
xzHnMPQNyN85zEqrB0Zx3kiHBtE/FhzQtxh/Idfz3E3tSI8nTMm4lH62rvPvc54F
19K1gWWzhxLkZC+tK20JUUSyuRdKEeO6SHptQYp8FdMeaYYLI/cHuArdS6L9zMia
BL4YXGpm1q3yXyTkwugHRSpYqyBzP8LksDJ57Oa2a+7CLZau5fw3JJODRDsuy9tT
XFKe3OeVA/H6g/AC0S9JkRCNuJ88q8n4KHCE4rK06uA+VIThymwZttylNHCAEF6w
kjmn45JwHKvRcf2m5ad9U5cVwJynBbvvW6/e1qNTh2ftopE/QUkhz3RO/5iLCpHB
MR6VenjcNEa86Nz2Q5V8Tf/8RXzNZ6GSPAAxlPCS43dZJLeVTscvm0TFVsFndBKq
iNYvcPlrXztv+0MRq9zdUjPKX6o/9/dA9y1doFBPQ1aqEhgPdVBrjzrMn7WiEgkg
eaxVVZbz/msqaAujFgEGZgey8AVPB7YcJJ+yuqRWlLnbtzyv1KzXguK+Xb6Ak4Et
yOjlqhH6SJ6oI8072WpqzyghDpoH9kyTjH//1HEK5VNuu1mF10ekwNUBOpBDDuyy
3CKm1RhdPyXF8mILp9OE80koq5K6tFwNS/hDERtQWt/s1CvtqKkSqdYRUIs+0sqt
YTBe2HubYTjmiGN38NfyNA==
-----END CERTIFICATE-----
root@jumpbox:~/kubernetes-the-hard-way# openssl x509 -in ca.crt -text -noout # 인증서 전체 내용 확인
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            71:23:13:b7:22:a8:5a:ac:9d:f9:85:d8:16:35:15:6b:03:62:3a:39
        Signature Algorithm: sha512WithRSAEncryption
        Issuer: C = US, ST = Washington, L = Seattle, CN = CA # kind는 kubernetes임
        Validity
            Not Before: Jan 10 22:05:56 2026 GMT
            Not After : Jan 11 22:05:56 2036 GMT
        Subject: C = US, ST = Washington, L = Seattle, CN = CA # kind는 kubernetes임
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (4096 bit)
                Modulus:
                    00:9e:d3:75:3e:1b:42:c8:18:06:5d:1a:55:c6:e6:
                    e2:27:3c:e1:4b:df:94:40:96:cf:1f:5c:a0:c5:8d:
                    e4:f5:47:81:7e:05:95:fc:99:50:d1:f6:4c:6e:8a:
                    31:8a:cd:9c:e4:01:8f:b8:9c:d8:9a:84:e7:16:67:
                    f7:a8:48:14:70:e4:2c:15:46:d2:14:89:11:49:03:
                    40:a0:8d:9d:4e:f3:03:20:42:b9:c7:ef:b1:93:aa:
                    bb:62:78:97:19:74:03:ee:dc:00:18:de:e0:a2:d9:
                    31:eb:71:47:d0:e9:41:32:82:80:18:d3:ea:d0:c7:
                    6a:17:41:19:ac:aa:ae:c9:30:99:65:23:ab:0e:c7:
                    24:ea:8f:b6:a6:52:39:79:e3:61:e5:cd:04:88:01:
                    0d:95:8b:56:f5:05:b2:ce:b0:bc:54:af:5c:5c:61:
                    c2:49:78:f3:85:3b:0d:24:01:7a:90:5a:39:69:33:
                    1f:98:5e:c2:c4:02:d3:8c:94:22:b0:9e:15:25:8c:
                    3e:1a:e4:dd:29:a8:34:33:8a:0a:fc:cb:76:24:b7:
                    a9:20:8c:62:c6:df:8f:30:91:79:80:ac:63:52:de:
                    53:d9:af:33:7e:ee:8b:05:3f:4f:2b:b4:dd:da:e8:
                    2e:2c:61:4e:f2:eb:41:68:e1:3c:38:26:1c:e9:fd:
                    20:96:a4:6d:76:b1:88:03:3b:af:03:a3:8a:7d:15:
                    f4:80:f0:9c:c6:8e:bb:41:33:f2:2e:d0:99:10:47:
                    99:ca:85:af:84:44:90:50:b9:dc:dc:7e:4f:b1:6f:
                    74:db:0a:2d:13:8f:c9:fc:6d:b4:ef:c7:7a:5d:38:
                    38:57:9f:e9:4b:c4:f8:e3:d0:a6:d9:ec:2e:5b:2a:
                    3a:32:c4:18:d9:85:66:18:7c:34:a8:bf:0b:82:00:
                    83:f4:c4:ea:bc:0d:61:60:fb:3c:8f:8e:ba:a9:15:
                    9b:b0:c8:39:d6:11:65:5a:4e:b2:a0:ee:44:fc:7e:
                    70:50:79:c1:4f:e2:ee:56:8b:62:f6:94:38:fe:16:
                    7c:ee:1e:8c:b0:29:4e:c8:2f:a5:13:71:48:d9:8f:
                    d2:02:98:df:58:a1:7d:b6:e2:21:c5:f7:2b:c2:e9:
                    e9:ae:ef:8b:f9:d5:7d:c7:ac:b3:9f:d2:3f:a8:1f:
                    19:bd:a2:b2:d6:72:87:e8:43:70:0e:73:bb:89:ee:
                    c5:fb:9d:60:a1:a6:6a:d0:45:9e:f8:7c:79:83:61:
                    29:bb:47:cf:fa:f3:ce:bb:e2:b4:ca:62:c1:89:76:
                    93:6c:02:82:48:ca:28:e1:96:68:a5:00:74:00:c5:
                    24:a2:cb:3a:1f:57:3a:44:5e:70:97:a6:65:62:4c:
                    b0:f9:91
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:TRUE
            X509v3 Key Usage:
                Certificate Sign, CRL Sign
            X509v3 Subject Key Identifier:
                9E:CD:36:BA:22:6B:43:A7:DB:23:29:97:53:1B:D1:72:DF:6D:61:D2
    Signature Algorithm: sha512WithRSAEncryption
    Signature Value:
        70:a6:bf:3e:f2:78:86:13:d5:23:00:a4:06:d8:03:64:c7:31:
        e7:30:f4:0d:c8:df:39:cc:4a:ab:07:46:71:de:48:87:06:d1:
        3f:16:1c:d0:b7:18:7f:21:d7:f3:dc:4d:ed:48:8f:27:4c:c9:
        b8:94:7e:b6:ae:f3:ef:73:9e:05:d7:d2:b5:81:65:b3:87:12:
        e4:64:2f:ad:2b:6d:09:51:44:b2:b9:17:4a:11:e3:ba:48:7a:
        6d:41:8a:7c:15:d3:1e:69:86:0b:23:f7:07:b8:0a:dd:4b:a2:
        fd:cc:c8:9a:04:be:18:5c:6a:66:d6:ad:f2:5f:24:e4:c2:e8:
        07:45:2a:58:ab:20:73:3f:c2:e4:b0:32:79:ec:e6:b6:6b:ee:
        c2:2d:96:ae:e5:fc:37:24:93:83:44:3b:2e:cb:db:53:5c:52:
        9e:dc:e7:95:03:f1:fa:83:f0:02:d1:2f:49:91:10:8d:b8:9f:
        3c:ab:c9:f8:28:70:84:e2:b2:b4:ea:e0:3e:54:84:e1:ca:6c:
        19:b6:dc:a5:34:70:80:10:5e:b0:92:39:a7:e3:92:70:1c:ab:
        d1:71:fd:a6:e5:a7:7d:53:97:15:c0:9c:a7:05:bb:ef:5b:af:
        de:d6:a3:53:87:67:ed:a2:91:3f:41:49:21:cf:74:4e:ff:98:
        8b:0a:91:c1:31:1e:95:7a:78:dc:34:46:bc:e8:dc:f6:43:95:
        7c:4d:ff:fc:45:7c:cd:67:a1:92:3c:00:31:94:f0:92:e3:77:
        59:24:b7:95:4e:c7:2f:9b:44:c5:56:c1:67:74:12:aa:88:d6:
        2f:70:f9:6b:5f:3b:6f:fb:43:11:ab:dc:dd:52:33:ca:5f:aa:
        3f:f7:f7:40:f7:2d:5d:a0:50:4f:43:56:aa:12:18:0f:75:50:
        6b:8f:3a:cc:9f:b5:a2:12:09:20:79:ac:55:55:96:f3:fe:6b:
        2a:68:0b:a3:16:01:06:66:07:b2:f0:05:4f:07:b6:1c:24:9f:
        b2:ba:a4:56:94:b9:db:b7:3c:af:d4:ac:d7:82:e2:be:5d:be:
        80:93:81:2d:c8:e8:e5:aa:11:fa:48:9e:a8:23:cd:3b:d9:6a:
        6a:cf:28:21:0e:9a:07:f6:4c:93:8c:7f:ff:d4:71:0a:e5:53:
        6e:bb:59:85:d7:47:a4:c0:d5:01:3a:90:43:0e:ec:b2:dc:22:
        a6:d5:18:5d:3f:25:c5:f2:62:0b:a7:d3:84:f3:49:28:ab:92:
        ba:b4:5c:0d:4b:f8:43:11:1b:50:5a:df:ec:d4:2b:ed:a8:a9:
        12:a9:d6:11:50:8b:3e:d2:ca:ad:61:30:5e:d8:7b:9b:61:38:
        e6:88:63:77:f0:d7:f2:34

 

Client, Server admin 인증서 생성하겠습니다.

root@jumpbox:~/kubernetes-the-hard-way# openssl genrsa -out admin.key 4096
root@jumpbox:~/kubernetes-the-hard-way# ls -l admin.key
-rw------- 1 root root 3272 Jan 11 07:19 admin.key
root@jumpbox:~/kubernetes-the-hard-way# cat ca.conf
[req]
distinguished_name = req_distinguished_name
prompt             = no
x509_extensions    = ca_x509_extensions

[ca_x509_extensions]
basicConstraints = CA:TRUE
keyUsage         = cRLSign, keyCertSign

[req_distinguished_name]
C   = US
ST  = Washington
L   = Seattle
CN  = CA

[admin] # ca.conf 에 admin 섹션 확인
distinguished_name = admin_distinguished_name
prompt             = no
req_extensions     = default_req_extensions

[admin_distinguished_name]
CN = admin
O  = system:masters

...



# csr 파일 생성 : admin.key 개인키를 사용해 'CN=admin, O=system:masters'인 Kubernetes 관리자용 클라이언트 인증서 요청(admin.csr) 생성
root@jumpbox:~/kubernetes-the-hard-way# openssl req -new -key admin.key -sha256 \
  -config ca.conf -section admin \
  -out admin.csr
root@jumpbox:~/kubernetes-the-hard-way#
root@jumpbox:~/kubernetes-the-hard-way# ls -l admin.csr
-rw-r--r-- 1 root root 1830 Jan 11 07:20 admin.csr
root@jumpbox:~/kubernetes-the-hard-way# openssl req -in admin.csr -text -noout # CSR 전체 내용 확인

Certificate Request:
    Data:
        Version: 1 (0x0)
        Subject: CN = admin, O = system:masters
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (4096 bit)
                Modulus:
                    00:b7:77:93:30:ae:01:ce:08:55:60:66:4e:35:a4:
                    c2:97:cc:10:22:d6:76:7c:02:20:3d:16:c7:11:a5:
                    ce:fa:44:5b:9c:7e:92:39:fa:50:2b:a1:82:ff:e2:
                    14:6f:80:74:7e:e1:58:14:fe:3f:06:c4:2c:1d:81:
                    7c:05:24:12:5f:ed:2d:84:b3:5b:11:7b:b6:ae:00:
                    5d:10:8c:a2:76:8c:37:a1:a3:67:34:75:cb:d3:66:
                    f5:64:86:0c:bc:7b:34:40:ef:e5:07:02:86:30:7e:
                    9b:47:67:97:2d:23:62:95:9d:75:55:b4:d0:33:1a:
                    34:85:da:e9:34:e7:cf:1e:89:2b:a0:c8:25:05:7a:
                    13:5d:94:6d:a1:c7:a3:4d:dd:f8:46:1f:8e:03:4c:
                    97:b3:41:83:9b:bb:08:59:f7:03:25:b6:07:9d:ea:
                    ed:0c:26:f4:22:ba:35:00:64:34:f9:9a:f9:ed:26:
                    e4:35:3c:f9:79:5f:37:69:59:ed:8b:db:7e:f7:42:
                    0c:15:ff:bb:1a:3e:f9:dd:b1:79:56:d1:96:b9:98:
                    ee:a0:76:52:49:8d:a9:73:26:c1:97:6b:fe:7a:eb:
                    39:24:3e:97:f7:e8:c2:85:4c:e3:99:8c:98:f5:76:
                    4f:8d:b1:b2:3e:45:5c:7a:db:c9:47:bd:95:3f:57:
                    09:ad:98:4d:3c:62:f1:82:d3:79:f0:99:f6:95:47:
                    58:c1:e3:e5:e1:f8:2a:a7:d9:f2:27:ae:d9:09:00:
                    6e:bb:96:50:b2:f4:ab:ac:84:db:27:f0:6d:01:8b:
                    26:fc:58:f7:8a:70:bc:e3:0e:c3:49:1e:b2:a2:67:
                    8e:c9:9b:1d:8a:43:90:0a:33:ed:d7:f9:70:f5:0a:
                    61:02:d9:99:49:1d:88:3c:c8:1b:e5:4c:75:28:99:
                    12:9e:6c:83:45:0b:f7:47:ac:ed:4d:31:df:f2:6d:
                    9e:99:26:0a:37:cd:31:3f:d3:b6:80:e4:c9:02:be:
                    d1:21:21:dd:48:0a:03:a8:39:40:14:1d:e7:5b:e2:
                    5b:0e:6b:9c:11:e1:58:da:28:bf:6f:ae:8d:d9:65:
                    0c:d3:e7:ef:00:6e:ee:7c:83:1c:be:e3:10:4b:c3:
                    77:e0:06:2e:54:f7:8a:8d:5c:bc:e9:8f:dc:d4:fb:
                    92:5d:f5:e5:f9:0c:ff:1a:a9:27:bf:28:ae:fd:f9:
                    e8:25:5b:02:11:cf:df:59:f0:ad:f8:d8:1a:cb:ed:
                    9b:00:45:b7:2e:76:63:b3:7b:e2:0f:44:75:a7:e6:
                    a8:eb:53:24:9e:95:a0:56:1b:71:0c:f6:10:a1:b0:
                    e9:c0:bd:c5:d8:3d:9b:d5:04:81:23:ba:7b:e3:88:
                    84:2c:b5
                Exponent: 65537 (0x10001)
        Attributes:
            Requested Extensions:
                X509v3 Basic Constraints:
                    CA:FALSE
                X509v3 Extended Key Usage:
                    TLS Web Client Authentication
                X509v3 Key Usage: critical
                    Digital Signature, Key Encipherment
                Netscape Cert Type:
                    SSL Client
                Netscape Comment:
                    Admin Client Certificate
                X509v3 Subject Key Identifier:
                    4C:56:38:B9:6E:E5:81:0A:70:F1:C9:02:CB:48:5C:8D:CE:B4:65:18
    Signature Algorithm: sha256WithRSAEncryption
    Signature Value:
        65:29:3a:20:5b:28:a2:86:5f:54:aa:0c:e5:57:11:9c:9c:87:
        b0:97:35:1b:f9:a0:f2:3d:c5:6f:e6:b3:73:fc:42:f7:b4:22:
        84:54:58:67:f9:7c:aa:18:e5:d7:2e:06:61:be:e7:53:8c:3c:
        87:49:09:ed:05:f5:b1:03:0a:cd:a8:52:df:a1:f4:92:db:ec:
        c0:f0:b8:ba:2b:10:b5:6b:eb:6a:e5:ec:08:f3:cf:3a:4d:0a:
        07:42:d2:a1:b3:3a:18:7d:d8:ae:07:04:c0:e2:fd:78:b8:31:
        0d:7a:d8:c1:aa:c2:d9:61:cd:ee:2e:6a:e8:bd:83:67:74:28:
        c7:1d:ca:c6:39:cd:cf:8c:3d:d6:57:63:0e:32:ea:0f:58:f5:
        43:db:76:95:b2:34:7f:ef:6a:1e:cb:af:22:14:c0:35:59:dc:
        02:30:69:7f:55:4c:82:ff:b5:e0:ec:eb:2b:2a:9a:b7:9e:c8:
        7f:8e:14:a6:09:82:7c:fa:82:2e:28:57:2e:5d:ec:8e:63:e8:
        a3:69:0a:42:3f:31:e7:5e:7b:fb:09:d5:64:69:30:04:ff:b6:
        67:e0:49:64:a0:2d:c7:c9:18:98:12:9d:3e:ba:c3:d5:41:00:
        a1:89:28:94:0f:90:9e:b6:23:cd:62:c7:b6:dd:cc:f7:da:32:
        84:9d:d2:a5:37:9b:7e:a5:c2:45:65:1e:97:ab:a0:4d:3f:2c:
        ff:00:43:cf:20:c9:37:a6:a3:cf:4f:a8:47:5a:f4:f2:be:10:
        20:19:e6:ee:c7:e1:c4:d2:f2:c1:da:84:f7:23:5d:bb:e5:a3:
        0e:ae:19:d0:4a:1b:7d:76:ff:89:5d:02:b4:26:4f:72:ba:37:
        aa:02:9d:1c:0e:5b:9a:a3:ff:ba:a2:4f:2f:bb:8e:a7:fa:5a:
        8d:78:e1:8e:61:55:f0:48:d3:b8:64:64:db:50:98:e0:3d:66:
        d1:fc:2b:19:f8:8d:da:36:5e:cb:0c:ae:f4:ec:e5:10:62:3e:
        1c:c0:8a:e6:d1:0e:b0:dd:74:80:da:8f:77:76:76:d3:0b:95:
        0f:c4:19:60:7a:e5:49:72:6a:63:0c:9e:8d:46:03:47:d4:36:
        16:36:a7:7a:ee:26:d9:6e:8d:d3:fb:79:40:7b:ff:2c:bb:35:
        be:35:1f:da:47:cb:e3:4d:dd:d7:f4:35:e5:2a:29:f3:32:7e:
        8c:2c:ce:89:6a:ad:0e:a7:a0:8e:77:06:75:eb:0d:10:9a:96:
        5d:10:98:3e:e7:8e:bb:92:dc:6e:2f:ad:14:79:82:ec:bf:14:
        4e:42:08:6a:34:29:f0:a9:5a:e6:58:86:9d:ea:34:92:50:aa:
        c8:4a:33:39:89:02:fd:2e
        

# ca에 csr 요청을 통한 crt 파일 생성
## -req : CSR를 입력으로 받아 인증서를 생성, self-signed 아님, CA가 서명하는 방식
## -days 3653 : 인증서 유효기간 3653일 (약 10년)
## -copy_extensions copyall : CSR에 포함된 모든 X.509 extensions를 인증서로 복사
## -CAcreateserial : CA 시리얼 번호 파일 자동 생성, 다음 인증서 발급 시 재사용, 기본 생성 파일(ca.srl)
openssl x509 -req -days 3653 -in admin.csr \
  -copy_extensions copyall \
  -sha256 -CA ca.crt \
  -CAkey ca.key \
  -CAcreateserial \
  -out admin.crt
Certificate request self-signature ok
subject=CN = admin, O = system:masters


root@jumpbox:~/kubernetes-the-hard-way# ls -l admin.crt
-rw-r--r-- 1 root root 2021 Jan 11 07:25 admin.crt
root@jumpbox:~/kubernetes-the-hard-way# openssl x509 -in admin.crt -text -noout
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            2b:03:f7:ba:63:e9:26:c8:a5:c1:9f:dd:8b:d8:df:4c:aa:56:f5:6f
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C = US, ST = Washington, L = Seattle, CN = CA
        Validity
            Not Before: Jan 10 22:25:09 2026 GMT
            Not After : Jan 11 22:25:09 2036 GMT
        Subject: CN = admin, O = system:masters # admin

 

Client, Server 인증서 나머지 전부에 대하여 생성하겠습니다.

# ca.conf 수정
root@jumpbox:~/kubernetes-the-hard-way# cat ca.conf | grep system:kube-scheduler
CN = system:kube-scheduler
O  = system:system:kube-scheduler

root@jumpbox:~/kubernetes-the-hard-way# sed -i 's/system:system:kube-scheduler/system:kube-scheduler/' ca.conf
root@jumpbox:~/kubernetes-the-hard-way# cat ca.conf | grep system:kube-scheduler
CN = system:kube-scheduler
O  = system:kube-scheduler

# 변수 지정
root@jumpbox:~/kubernetes-the-hard-way# certs=(
  "node-0" "node-1"
  "kube-proxy" "kube-scheduler"
  "kube-controller-manager"
  "kube-api-server"
  "service-accounts"
)

# 확인
root@jumpbox:~/kubernetes-the-hard-way# echo ${certs[*]}
node-0 node-1 kube-proxy kube-scheduler kube-controller-manager kube-api-server service-accounts

# 개인키 생성, csr 생성, 인증서 생성
root@jumpbox:~/kubernetes-the-hard-way# for i in ${certs[*]}; do
  openssl genrsa -out "${i}.key" 4096

  openssl req -new -key "${i}.key" -sha256 \
    -config "ca.conf" -section ${i} \
    -out "${i}.csr"

  openssl x509 -req -days 3653 -in "${i}.csr" \
    -copy_extensions copyall \
    -sha256 -CA "ca.crt" \
    -CAkey "ca.key" \
    -CAcreateserial \
    -out "${i}.crt"
done
Certificate request self-signature ok
subject=CN = system:node:node-0, O = system:nodes, C = US, ST = Washington, L = Seattle
Certificate request self-signature ok
subject=CN = system:node:node-1, O = system:nodes, C = US, ST = Washington, L = Seattle
Certificate request self-signature ok
subject=CN = system:kube-proxy, O = system:node-proxier, C = US, ST = Washington, L = Seattle
Certificate request self-signature ok
subject=CN = system:kube-scheduler, O = system:kube-scheduler, C = US, ST = Washington, L = Seattle
Certificate request self-signature ok
subject=CN = system:kube-controller-manager, O = system:kube-controller-manager, C = US, ST = Washington, L = Seattle
Certificate request self-signature ok
subject=CN = kubernetes, C = US, ST = Washington, L = Seattle
Certificate request self-signature ok
subject=CN = service-accounts


root@jumpbox:~/kubernetes-the-hard-way# ls -1 *.crt *.key *.csr
admin.crt
admin.csr
admin.key
ca.crt
ca.key
kube-api-server.crt
kube-api-server.csr
kube-api-server.key
kube-controller-manager.crt
kube-controller-manager.csr
kube-controller-manager.key
kube-proxy.crt
kube-proxy.csr
kube-proxy.key
kube-scheduler.crt
kube-scheduler.csr
kube-scheduler.key
node-0.crt
node-0.csr
node-0.key
node-1.crt
node-1.csr
node-1.key
service-accounts.crt
service-accounts.csr
service-accounts.key


root@jumpbox:~/kubernetes-the-hard-way# openssl x509 -in node-0.crt -text -noout
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            2b:03:f7:ba:63:e9:26:c8:a5:c1:9f:dd:8b:d8:df:4c:aa:56:f5:70
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C = US, ST = Washington, L = Seattle, CN = CA
        Validity
            Not Before: Jan 10 22:28:48 2026 GMT
            Not After : Jan 11 22:28:48 2036 GMT
        Subject: CN = system:node:node-0, O = system:nodes, C = US, ST = Washington, L = Seattle
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (4096 bit)
                Modulus:
                    00:d3:fe:f2:c0:df:bb:08:76:6d:ef:1b:c5:25:e0:
                    16:66:be:d1:36:b0:2e:6b:9a:c5:d7:79:f9:36:da:
                    2b:cb:95:91:94:1b:75:92:f5:87:26:0b:a8:8c:e5:
                    a0:07:e6:c3:01:71:61:c1:f1:40:43:57:1d:63:bb:
                    51:c6:fd:81:ab:e0:83:40:b0:29:78:6f:22:30:63:
                    17:21:6e:41:31:37:39:b9:af:5f:8c:0c:ad:87:d8:
                    81:95:c6:d4:be:6e:f9:da:1b:1c:c8:a3:0f:72:3c:
                    77:2a:7a:1b:2b:71:40:85:a3:e4:fb:5e:d5:81:14:
                    a0:15:99:ce:6a:c4:1f:50:3a:4f:a9:10:17:bb:dc:
                    e9:e2:ba:03:48:e9:19:ec:8b:94:1d:d6:93:1b:57:
                    46:ee:25:39:d3:9b:3b:4a:1b:8c:71:ff:21:ff:60:
                    78:4f:b2:0a:10:cf:da:73:a9:4b:dc:f1:50:2d:c5:
                    82:0b:44:34:cb:40:87:dc:07:3b:88:1f:ce:c3:85:
                    c5:12:b7:f3:13:4d:77:e0:7d:60:a9:5b:ac:81:3c:
                    3f:79:63:b0:88:27:a9:92:e2:c2:bd:86:0e:e8:f2:
                    ed:bb:bf:2f:ed:14:f0:50:cf:bb:a3:8d:8e:8e:e5:
                    be:45:72:ad:83:78:1e:da:4d:4e:9f:d9:4f:6d:5b:
                    2b:25:8d:80:67:5b:bd:a5:13:b8:d3:1a:35:61:9c:
                    8b:c6:e7:b5:45:6e:d2:5e:82:b5:19:ee:6a:92:14:
                    b7:ef:04:66:8a:b3:94:0a:44:bf:d2:40:c3:62:7d:
                    15:f3:50:4b:9f:76:41:6c:87:15:5c:ac:74:26:cc:
                    c6:51:29:c0:e1:35:52:d1:8c:45:c1:93:17:e2:45:
                    88:8d:9f:23:4e:19:9d:4e:df:40:59:3a:f0:e7:12:
                    57:fe:da:72:f8:a7:1b:4e:be:45:75:5f:32:94:69:
                    11:02:4f:a9:6a:53:b9:23:62:88:42:b6:16:ec:f9:
                    64:31:ea:8d:6d:f1:f1:d1:da:ec:9f:b9:a9:da:a6:
                    27:39:e8:4e:e4:0f:62:11:e2:44:0c:aa:7c:44:19:
                    85:8f:29:35:b8:63:6d:df:85:9d:19:86:c3:49:6f:
                    ad:57:f6:03:3f:8f:c7:56:3b:24:a1:9b:c6:85:6d:
                    70:98:7b:46:2a:06:93:bc:88:0f:33:c4:3d:de:0c:
                    79:e2:c3:0f:68:57:2c:07:bc:b4:e4:04:f5:f8:0b:
                    ce:5e:b7:80:f5:bc:44:df:aa:eb:38:34:c4:a3:e1:
                    34:b3:24:21:42:f4:10:c8:13:a8:32:66:0f:c6:84:
                    bb:6b:ff:58:fa:b9:3d:16:c5:9c:f0:be:2d:9e:7b:
                    4d:b0:f9
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:FALSE
            X509v3 Extended Key Usage:
                TLS Web Client Authentication, TLS Web Server Authentication
            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment
            Netscape Cert Type:
                SSL Client
            Netscape Comment:
                Node-0 Certificate
            X509v3 Subject Alternative Name:
                DNS:node-0, IP Address:127.0.0.1 # DNS:node-0
            X509v3 Subject Key Identifier:
                F0:75:8C:46:52:57:57:BF:C3:36:4E:CB:92:2B:4D:F1:32:D7:69:E0
            X509v3 Authority Key Identifier:
                9E:CD:36:BA:22:6B:43:A7:DB:23:29:97:53:1B:D1:72:DF:6D:61:D2
    Signature Algorithm: sha256WithRSAEncryption
    Signature Value:
        16:15:df:57:75:b0:6d:6e:8d:35:52:d6:43:07:61:cd:f3:00:
        60:d2:6a:1d:81:da:55:98:24:88:ce:c2:59:42:0b:b1:83:a7:
        de:71:41:df:02:b4:53:9e:3b:6c:bd:de:85:97:c1:d7:71:8a:
        33:aa:49:88:67:a6:74:4a:d8:80:68:cb:2e:a1:ae:52:ac:74:
        44:02:41:0c:79:15:6f:d7:48:56:9e:d8:41:0f:b3:f2:31:dc:
        b6:6b:f1:09:e7:af:df:75:6a:fd:be:d5:dd:69:20:8e:66:5f:
        88:f3:13:c3:49:e5:c8:ca:59:ce:83:1c:df:20:38:4f:e3:13:
        93:d4:3d:c7:fb:63:85:d6:5d:14:90:4c:c9:45:42:e3:54:e6:
        e6:b7:c1:ec:b9:a1:68:eb:d5:1b:28:cc:bc:cc:07:94:fa:a2:
        49:c0:14:19:55:b2:42:2b:04:c3:47:39:74:70:67:ac:8b:24:
        1e:0a:e4:86:3a:1d:56:18:f3:96:e2:f4:d6:20:34:be:dd:79:
        2f:b6:d6:4a:ed:c5:09:a3:42:9b:f3:c4:bd:99:ed:5a:05:27:
        ce:2b:b6:48:de:49:39:5d:23:c3:3a:f5:28:1d:37:16:6f:93:
        9b:15:4e:78:27:63:e1:de:1b:1e:36:66:d6:3f:e9:32:f0:41:
        4c:c2:cd:65:06:70:40:a6:0a:55:5f:47:77:3a:eb:03:35:6f:
        5a:06:75:c1:8f:81:f8:fd:2b:58:dd:d9:2d:d6:12:e1:f2:ae:
        14:3e:7b:af:96:25:7d:68:29:d1:4b:bb:56:03:26:d9:a4:4d:
        ae:bd:ac:93:ff:e3:7b:4f:17:d8:b8:d2:3f:a4:a4:da:73:4d:
        1d:a1:b0:1d:b7:68:56:f2:d5:b9:6b:52:b3:cc:09:f5:55:16:
        52:b7:a3:aa:36:54:13:72:7f:01:53:ca:79:e5:5e:84:87:40:
        7e:c4:d7:c3:8b:20:32:e4:67:3f:4d:cd:33:d0:92:03:31:49:
        c7:e2:2e:15:e7:16:a3:fa:dc:f8:cf:61:44:c8:ed:eb:ad:cc:
        50:1a:0e:72:19:30:cb:22:86:6a:bd:24:24:18:b5:27:54:b1:
        c4:96:cd:f3:d4:ba:9b:ec:7d:34:80:76:9e:24:10:b4:56:fa:
        9f:4a:81:60:f2:57:ad:d2:45:ce:65:aa:c8:95:24:6f:e4:6b:
        3f:9f:fc:d6:cb:34:54:09:2a:8c:17:6c:c8:4d:0f:ba:b4:d4:
        c5:ff:e5:14:2c:fb:50:34:c4:f6:87:12:44:ea:e7:b9:e3:84:
        d8:06:1b:b8:a7:a6:26:bd:c3:bf:7e:e0:0c:72:9e:38:42:8f:
        ec:ea:c3:43:ce:b3:26:69


root@jumpbox:~/kubernetes-the-hard-way# openssl x509 -in node-1.crt -text -noout
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            2b:03:f7:ba:63:e9:26:c8:a5:c1:9f:dd:8b:d8:df:4c:aa:56:f5:71
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C = US, ST = Washington, L = Seattle, CN = CA
        Validity
            Not Before: Jan 10 22:28:50 2026 GMT
            Not After : Jan 11 22:28:50 2036 GMT
        Subject: CN = system:node:node-1, O = system:nodes, C = US, ST = Washington, L = Seattle
        ...
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:FALSE
            X509v3 Extended Key Usage:
                TLS Web Client Authentication, TLS Web Server Authentication
            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment
            Netscape Cert Type:
                SSL Client
            Netscape Comment:
                Node-1 Certificate
            X509v3 Subject Alternative Name:
                DNS:node-1, IP Address:127.0.0.1

root@jumpbox:~/kubernetes-the-hard-way# openssl x509 -in kube-proxy.crt -text -noout
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            2b:03:f7:ba:63:e9:26:c8:a5:c1:9f:dd:8b:d8:df:4c:aa:56:f5:72
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C = US, ST = Washington, L = Seattle, CN = CA
        Validity
            Not Before: Jan 10 22:28:52 2026 GMT
            Not After : Jan 11 22:28:52 2036 GMT
        Subject: CN = system:kube-proxy, O = system:node-proxier, C = US, ST = Washington, L = Seattle
        ...
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:FALSE
            X509v3 Extended Key Usage:
                TLS Web Client Authentication, TLS Web Server Authentication
            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment
            Netscape Cert Type:
                SSL Client
            Netscape Comment:
                Kube Proxy Certificate
            X509v3 Subject Alternative Name:
                DNS:kube-proxy, IP Address:127.0.0.1
            X509v3 Subject Key Identifier:
                BE:7D:4E:DC:92:C0:AA:B9:6C:41:1E:D5:2F:A2:C6:26:79:F5:63:52
            X509v3 Authority Key Identifier:
                9E:CD:36:BA:22:6B:43:A7:DB:23:29:97:53:1B:D1:72:DF:6D:61:D2


# 아래 컴포넌트에 대해서도 모두 CN = system:컴포넌트, X509v3 Subject Alternative Name:DNS:컴포넌트 동일
root@jumpbox:~/kubernetes-the-hard-way# openssl x509 -in kube-scheduler.crt -text -noout
root@jumpbox:~/kubernetes-the-hard-way# openssl x509 -in kube-controller-manager.crt -text -noout
root@jumpbox:~/kubernetes-the-hard-way# openssl x509 -in kube-api-server.crt -text -noout
root@jumpbox:~/kubernetes-the-hard-way# openssl x509 -in service-accounts.crt -text -noout

 

각 VM에게 Client, Server 인증서를 나누어줍니다.

root@jumpbox:~/kubernetes-the-hard-way# for host in node-0 node-1; do
  ssh root@${host} mkdir /var/lib/kubelet/

  scp ca.crt root@${host}:/var/lib/kubelet/

  scp ${host}.crt \
    root@${host}:/var/lib/kubelet/kubelet.crt

  scp ${host}.key \
    root@${host}:/var/lib/kubelet/kubelet.key
done
ca.crt                                                                                                                                                       100% 1899     2.5MB/s   00:00
node-0.crt                                                                                                                                                   100% 2147     3.4MB/s   00:00
node-0.key                                                                                                                                                   100% 3272     4.2MB/s   00:00
ca.crt                                                                                                                                                       100% 1899     2.9MB/s   00:00
node-1.crt                                                                                                                                                   100% 2147     3.2MB/s   00:00
node-1.key                                                                                                                                                   100% 3272     5.1MB/s   00:00

root@jumpbox:~/kubernetes-the-hard-way# ssh node-0 ls -l /var/lib/kubelet
total 12
-rw-r--r-- 1 root root 1899 Jan 11 07:35 ca.crt
-rw-r--r-- 1 root root 2147 Jan 11 07:35 kubelet.crt
-rw------- 1 root root 3272 Jan 11 07:35 kubelet.key
root@jumpbox:~/kubernetes-the-hard-way# ssh node-1 ls -l /var/lib/kubelet
total 12
-rw-r--r-- 1 root root 1899 Jan 11 07:35 ca.crt
-rw-r--r-- 1 root root 2147 Jan 11 07:35 kubelet.crt
-rw------- 1 root root 3272 Jan 11 07:35 kubelet.key

root@jumpbox:~/kubernetes-the-hard-way# scp \
  ca.key ca.crt \
  kube-api-server.key kube-api-server.crt \
  service-accounts.key service-accounts.crt \
  root@server:~/
ca.key                                                                                                                                                       100% 3272     2.8MB/s   00:00
ca.crt                                                                                                                                                       100% 1899     2.0MB/s   00:00
kube-api-server.key                                                                                                                                          100% 3268     3.3MB/s   00:00
kube-api-server.crt                                                                                                                                          100% 2354     1.7MB/s   00:00
service-accounts.key                                                                                                                                         100% 3272     3.3MB/s   00:00
service-accounts.crt                                                                                                                                         100% 2004     1.9MB/s   00:00

root@jumpbox:~/kubernetes-the-hard-way# ssh server ls -l /root
total 24
-rw-r--r-- 1 root root 1899 Jan 11 07:36 ca.crt
-rw------- 1 root root 3272 Jan 11 07:36 ca.key
-rw-r--r-- 1 root root 2354 Jan 11 07:36 kube-api-server.crt
-rw------- 1 root root 3268 Jan 11 07:36 kube-api-server.key
-rw-r--r-- 1 root root 2004 Jan 11 07:36 service-accounts.crt
-rw------- 1 root root 3272 Jan 11 07:36 service-accounts.key

 

 

인증을 위한 Kubernetes 설정 파일 생성

API Server와 통신을 위한 Client 인증 설정 파일을 작성하겠습니다.

우선, kubelet 전용 kubeconfig 파일을 생성하겠습니다.

각 kubelet이 API Server에 ‘자기 자신’으로 인증·인가받을 수 있도록 kubeconfig(클라이언트 인증 설정 파일)를 만들어주는 단계입니다.

kubelet은 API Server에 클라이언트로 요청을 보낼때, 이 요청들은 익명 요청이 아니라 인증된 요청이어야합니다.

kubelet 인증서의 Subject CN이 반드시 system:node:<node-name> 형태여야 합니다.

따라서, node-0, node-1의 kubeconfig 파일을 생성하겠습니다.

root@jumpbox:~/kubernetes-the-hard-way# kubectl describe pod -n kube-system kube-apiserver-myk8s-control-plane
...
    Command:
      kube-apiserver
      --authorization-mode=Node,RBAC  
...


# config set-cluster
root@jumpbox:~/kubernetes-the-hard-way# kubectl config set-cluster kubernetes-the-hard-way \
  --certificate-authority=ca.crt \
  --embed-certs=true \
  --server=https://server.kubernetes.local:6443 \
  --kubeconfig=node-0.kubeconfig && ls -l node-0.kubeconfig && cat node-0.kubeconfig
Cluster "kubernetes-the-hard-way" set.
-rw------- 1 root root 2758 Jan 11 07:47 node-0.kubeconfig
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUZURENDQXpTZ0F3SUJBZ0lVY1NNVHR5S29XcXlkK1lYWUZqVVZhd05pT2prd0RRWUpLb1pJaHZjTkFRRU4KQlFBd1FURUxNQWtHQTFVRUJoTUNWVk14RXpBUkJnTlZCQWdNQ2xkaGMyaHBibWQwYjI0eEVEQU9CZ05WQkFjTQpCMU5sWVhSMGJHVXhDekFKQmdOVkJBTU1Ba05CTUI0WERUSTJNREV4TURJeU1EVTFObG9YRFRNMk1ERXhNVEl5Ck1EVTFObG93UVRFTE1Ba0dBMVVFQmhNQ1ZWTXhFekFSQmdOVkJBZ01DbGRoYzJocGJtZDBiMjR4RURBT0JnTlYKQkFjTUIxTmxZWFIwYkdVeEN6QUpCZ05WQkFNTUFrTkJNSUlDSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQWc4QQpNSUlDQ2dLQ0FnRUFudE4xUGh0Q3lCZ0dYUnBWeHViaUp6emhTOStVUUpiUEgxeWd4WTNrOVVlQmZnV1YvSmxRCjBmWk1ib294aXMyYzVBR1B1SnpZbW9UbkZtZjNxRWdVY09Rc0ZVYlNGSWtSU1FOQW9JMmRUdk1ESUVLNXgrK3gKazZxN1luaVhHWFFEN3R3QUdON2dvdGt4NjNGSDBPbEJNb0tBR05QcTBNZHFGMEVacktxdXlUQ1paU09yRHNjawo2bysycGxJNWVlTmg1YzBFaUFFTmxZdFc5UVd5enJDOFZLOWNYR0hDU1hqemhUc05KQUY2a0ZvNWFUTWZtRjdDCnhBTFRqSlFpc0o0VkpZdytHdVRkS2FnME00b0svTXQySkxlcElJeGl4dCtQTUpGNWdLeGpVdDVUMmE4emZ1NkwKQlQ5UEs3VGQydWd1TEdGTzh1dEJhT0U4T0NZYzZmMGdscVJ0ZHJHSUF6dXZBNk9LZlJYMGdQQ2N4bzY3UVRQeQpMdENaRUVlWnlvV3ZoRVNRVUxuYzNINVBzVzkwMndvdEU0L0ovRzIwNzhkNlhUZzRWNS9wUzhUNDQ5Q20yZXd1Cld5bzZNc1FZMllWbUdIdzBxTDhMZ2dDRDlNVHF2QTFoWVBzOGo0NjZxUldic01nNTFoRmxXazZ5b081RS9INXcKVUhuQlQrTHVWb3RpOXBRNC9oWjg3aDZNc0NsT3lDK2xFM0ZJMlkvU0FwamZXS0Y5dHVJaHhmY3J3dW5wcnUrTAorZFY5eDZ5em45SS9xQjhadmFLeTFuS0g2RU53RG5PN2llN0YrNTFnb2FacTBFV2UrSHg1ZzJFcHUwZlArdlBPCnUrSzB5bUxCaVhhVGJBS0NTTW9vNFpab3BRQjBBTVVrb3NzNkgxYzZSRjV3bDZabFlreXcrWkVDQXdFQUFhTTgKTURvd0RBWURWUjBUQkFVd0F3RUIvekFMQmdOVkhROEVCQU1DQVFZd0hRWURWUjBPQkJZRUZKN05Ocm9pYTBPbgoyeU1wbDFNYjBYTGZiV0hTTUEwR0NTcUdTSWIzRFFFQkRRVUFBNElDQVFCd3ByOCs4bmlHRTlVakFLUUcyQU5rCnh6SG5NUFFOeU44NXpFcXJCMFp4M2tpSEJ0RS9GaHpRdHhoL0lkZnozRTN0U0k4blRNbTRsSDYycnZQdmM1NEYKMTlLMWdXV3poeExrWkMrdEsyMEpVVVN5dVJkS0VlTzZTSHB0UVlwOEZkTWVhWVlMSS9jSHVBcmRTNkw5ek1pYQpCTDRZWEdwbTFxM3lYeVRrd3VnSFJTcFlxeUJ6UDhMa3NESjU3T2EyYSs3Q0xaYXU1ZnczSkpPRFJEc3V5OXRUClhGS2UzT2VWQS9INmcvQUMwUzlKa1JDTnVKODhxOG40S0hDRTRySzA2dUErVklUaHltd1p0dHlsTkhDQUVGNncKa2ptbjQ1SndIS3ZSY2YybTVhZDlVNWNWd0p5bkJidnZXNi9lMXFOVGgyZnRvcEUvUVVraHozUk8vNWlMQ3BIQgpNUjZWZW5qY05FYTg2TnoyUTVWOFRmLzhSWHpOWjZHU1BBQXhsUENTNDNkWkpMZVZUc2N2bTBURlZzRm5kQktxCmlOWXZjUGxyWHp0diswTVJxOXpkVWpQS1g2by85L2RBOXkxZG9GQlBRMWFxRWhnUGRWQnJqenJNbjdXaUVna2cKZWF4VlZaYnovbXNxYUF1akZnRUdaZ2V5OEFWUEI3WWNKSit5dXFSV2xMbmJ0enl2MUt6WGd1SytYYjZBazRFdAp5T2pscWhINlNKNm9JODA3MldwcXp5Z2hEcG9IOWt5VGpILy8xSEVLNVZOdXUxbUYxMGVrd05VQk9wQkREdXl5CjNDS20xUmhkUHlYRjhtSUxwOU9FODBrb3E1SzZ0RndOUy9oREVSdFFXdC9zMUN2dHFLa1NxZFlSVUlzKzBzcXQKWVRCZTJIdWJZVGptaUdOMzhOZnlOQT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
    server: https://server.kubernetes.local:6443
  name: kubernetes-the-hard-way
contexts: null
current-context: ""
kind: Config
preferences: {}
users: null

root@jumpbox:~/kubernetes-the-hard-way# kubectl config set-cluster kubernetes-the-hard-way \
  --certificate-authority=ca.crt \
  --embed-certs=true \
  --server=https://server.kubernetes.local:6443 \
  --kubeconfig=node-1.kubeconfig && ls -l node-1.kubeconfig && cat node-1.kubeconfig
  
# config set-credentials
root@jumpbox:~/kubernetes-the-hard-way# kubectl config set-credentials system:node:node-0 \
  --client-certificate=node-0.crt \
  --client-key=node-0.key \
  --embed-certs=true \
  --kubeconfig=node-0.kubeconfig && cat node-0.kubeconfig
User "system:node:node-0" set.
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUZURENDQXpTZ0F3SUJBZ0lVY1NNVHR5S29XcXlkK1lYWUZqVVZhd05pT2prd0RRWUpLb1pJaHZjTkFRRU4KQlFBd1FURUxNQWtHQTFVRUJoTUNWVk14RXpBUkJnTlZCQWdNQ2xkaGMyaHBibWQwYjI0eEVEQU9CZ05WQkFjTQpCMU5sWVhSMGJHVXhDekFKQmdOVkJBTU1Ba05CTUI0WERUSTJNREV4TURJeU1EVTFObG9YRFRNMk1ERXhNVEl5Ck1EVTFObG93UVRFTE1Ba0dBMVVFQmhNQ1ZWTXhFekFSQmdOVkJBZ01DbGRoYzJocGJtZDBiMjR4RURBT0JnTlYKQkFjTUIxTmxZWFIwYkdVeEN6QUpCZ05WQkFNTUFrTkJNSUlDSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQWc4QQpNSUlDQ2dLQ0FnRUFudE4xUGh0Q3lCZ0dYUnBWeHViaUp6emhTOStVUUpiUEgxeWd4WTNrOVVlQmZnV1YvSmxRCjBmWk1ib294aXMyYzVBR1B1SnpZbW9UbkZtZjNxRWdVY09Rc0ZVYlNGSWtSU1FOQW9JMmRUdk1ESUVLNXgrK3gKazZxN1luaVhHWFFEN3R3QUdON2dvdGt4NjNGSDBPbEJNb0tBR05QcTBNZHFGMEVacktxdXlUQ1paU09yRHNjawo2bysycGxJNWVlTmg1YzBFaUFFTmxZdFc5UVd5enJDOFZLOWNYR0hDU1hqemhUc05KQUY2a0ZvNWFUTWZtRjdDCnhBTFRqSlFpc0o0VkpZdytHdVRkS2FnME00b0svTXQySkxlcElJeGl4dCtQTUpGNWdLeGpVdDVUMmE4emZ1NkwKQlQ5UEs3VGQydWd1TEdGTzh1dEJhT0U4T0NZYzZmMGdscVJ0ZHJHSUF6dXZBNk9LZlJYMGdQQ2N4bzY3UVRQeQpMdENaRUVlWnlvV3ZoRVNRVUxuYzNINVBzVzkwMndvdEU0L0ovRzIwNzhkNlhUZzRWNS9wUzhUNDQ5Q20yZXd1Cld5bzZNc1FZMllWbUdIdzBxTDhMZ2dDRDlNVHF2QTFoWVBzOGo0NjZxUldic01nNTFoRmxXazZ5b081RS9INXcKVUhuQlQrTHVWb3RpOXBRNC9oWjg3aDZNc0NsT3lDK2xFM0ZJMlkvU0FwamZXS0Y5dHVJaHhmY3J3dW5wcnUrTAorZFY5eDZ5em45SS9xQjhadmFLeTFuS0g2RU53RG5PN2llN0YrNTFnb2FacTBFV2UrSHg1ZzJFcHUwZlArdlBPCnUrSzB5bUxCaVhhVGJBS0NTTW9vNFpab3BRQjBBTVVrb3NzNkgxYzZSRjV3bDZabFlreXcrWkVDQXdFQUFhTTgKTURvd0RBWURWUjBUQkFVd0F3RUIvekFMQmdOVkhROEVCQU1DQVFZd0hRWURWUjBPQkJZRUZKN05Ocm9pYTBPbgoyeU1wbDFNYjBYTGZiV0hTTUEwR0NTcUdTSWIzRFFFQkRRVUFBNElDQVFCd3ByOCs4bmlHRTlVakFLUUcyQU5rCnh6SG5NUFFOeU44NXpFcXJCMFp4M2tpSEJ0RS9GaHpRdHhoL0lkZnozRTN0U0k4blRNbTRsSDYycnZQdmM1NEYKMTlLMWdXV3poeExrWkMrdEsyMEpVVVN5dVJkS0VlTzZTSHB0UVlwOEZkTWVhWVlMSS9jSHVBcmRTNkw5ek1pYQpCTDRZWEdwbTFxM3lYeVRrd3VnSFJTcFlxeUJ6UDhMa3NESjU3T2EyYSs3Q0xaYXU1ZnczSkpPRFJEc3V5OXRUClhGS2UzT2VWQS9INmcvQUMwUzlKa1JDTnVKODhxOG40S0hDRTRySzA2dUErVklUaHltd1p0dHlsTkhDQUVGNncKa2ptbjQ1SndIS3ZSY2YybTVhZDlVNWNWd0p5bkJidnZXNi9lMXFOVGgyZnRvcEUvUVVraHozUk8vNWlMQ3BIQgpNUjZWZW5qY05FYTg2TnoyUTVWOFRmLzhSWHpOWjZHU1BBQXhsUENTNDNkWkpMZVZUc2N2bTBURlZzRm5kQktxCmlOWXZjUGxyWHp0diswTVJxOXpkVWpQS1g2by85L2RBOXkxZG9GQlBRMWFxRWhnUGRWQnJqenJNbjdXaUVna2cKZWF4VlZaYnovbXNxYUF1akZnRUdaZ2V5OEFWUEI3WWNKSit5dXFSV2xMbmJ0enl2MUt6WGd1SytYYjZBazRFdAp5T2pscWhINlNKNm9JODA3MldwcXp5Z2hEcG9IOWt5VGpILy8xSEVLNVZOdXUxbUYxMGVrd05VQk9wQkREdXl5CjNDS20xUmhkUHlYRjhtSUxwOU9FODBrb3E1SzZ0RndOUy9oREVSdFFXdC9zMUN2dHFLa1NxZFlSVUlzKzBzcXQKWVRCZTJIdWJZVGptaUdOMzhOZnlOQT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
    server: https://server.kubernetes.local:6443
  name: kubernetes-the-hard-way
contexts: null
current-context: ""
kind: Config
preferences: {}
users:
- name: system:node:node-0
  user:
    client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUdCRENDQSt5Z0F3SUJBZ0lVS3dQM3VtUHBKc2lsd1ovZGk5amZUS3BXOVhBd0RRWUpLb1pJaHZjTkFRRUwKQlFBd1FURUxNQWtHQTFVRUJoTUNWVk14RXpBUkJnTlZCQWdNQ2xkaGMyaHBibWQwYjI0eEVEQU9CZ05WQkFjTQpCMU5sWVhSMGJHVXhDekFKQmdOVkJBTU1Ba05CTUI0WERUSTJNREV4TURJeU1qZzBPRm9YRFRNMk1ERXhNVEl5Ck1qZzBPRm93YURFYk1Ca0dBMVVFQXd3U2MzbHpkR1Z0T201dlpHVTZibTlrWlMwd01SVXdFd1lEVlFRS0RBeHoKZVhOMFpXMDZibTlrWlhNeEN6QUpCZ05WQkFZVEFsVlRNUk13RVFZRFZRUUlEQXBYWVhOb2FXNW5kRzl1TVJBdwpEZ1lEVlFRSERBZFRaV0YwZEd4bE1JSUNJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBZzhBTUlJQ0NnS0NBZ0VBCjAvN3l3Tis3Q0hadDd4dkZKZUFXWnI3Uk5yQXVhNXJGMTNuNU50b3J5NVdSbEJ0MWt2V0hKZ3Vvak9XZ0IrYkQKQVhGaHdmRkFRMWNkWTd0Unh2MkJxK0NEUUxBcGVHOGlNR01YSVc1Qk1UYzV1YTlmakF5dGg5aUJsY2JVdm03NQoyaHNjeUtNUGNqeDNLbm9iSzNGQWhhUGsrMTdWZ1JTZ0Zabk9hc1FmVURwUHFSQVh1OXpwNHJvRFNPa1o3SXVVCkhkYVRHMWRHN2lVNTA1czdTaHVNY2Y4aC8yQjRUN0lLRU0vYWM2bEwzUEZRTGNXQ0MwUTB5MENIM0FjN2lCL08KdzRYRkVyZnpFMDEzNEgxZ3FWdXNnVHcvZVdPd2lDZXBrdUxDdllZTzZQTHR1Nzh2N1JUd1VNKzdvNDJPanVXKwpSWEt0ZzNnZTJrMU9uOWxQYlZzckpZMkFaMXU5cFJPNDB4bzFZWnlMeHVlMVJXN1NYb0sxR2U1cWtoUzM3d1JtCmlyT1VDa1MvMGtERFluMFY4MUJMbjNaQmJJY1ZYS3gwSnN6R1VTbkE0VFZTMFl4RndaTVg0a1dJalo4alRobWQKVHQ5QVdUcnc1eEpYL3RweStLY2JUcjVGZFY4eWxHa1JBaytwYWxPNUkyS0lRcllXN1Bsa01lcU5iZkh4MGRycwpuN21wMnFZbk9laE81QTlpRWVKRURLcDhSQm1GanlrMXVHTnQzNFdkR1liRFNXK3RWL1lEUDQvSFZqc2tvWnZHCmhXMXdtSHRHS2dhVHZJZ1BNOFE5M2d4NTRzTVBhRmNzQjd5MDVBVDErQXZPWHJlQTlieEUzNnJyT0RURW8rRTAKc3lRaFF2UVF5Qk9vTW1ZUHhvUzdhLzlZK3JrOUZzV2M4TDR0bm50TnNQa0NBd0VBQWFPQnpEQ0J5VEFKQmdOVgpIUk1FQWpBQU1CMEdBMVVkSlFRV01CUUdDQ3NHQVFVRkJ3TUNCZ2dyQmdFRkJRY0RBVEFPQmdOVkhROEJBZjhFCkJBTUNCYUF3RVFZSllJWklBWWI0UWdFQkJBUURBZ2VBTUNFR0NXQ0dTQUdHK0VJQkRRUVVGaEpPYjJSbExUQWcKUTJWeWRHbG1hV05oZEdVd0Z3WURWUjBSQkJBd0RvSUdibTlrWlMwd2h3Ui9BQUFCTUIwR0ExVWREZ1FXQkJUdwpkWXhHVWxkWHY4TTJUc3VTSzAzeE10ZHA0REFmQmdOVkhTTUVHREFXZ0JTZXpUYTZJbXREcDlzaktaZFRHOUZ5CjMyMWgwakFOQmdrcWhraUc5dzBCQVFzRkFBT0NBZ0VBRmhYZlYzV3diVzZOTlZMV1F3ZGh6Zk1BWU5KcUhZSGEKVlpna2lNN0NXVUlMc1lPbjNuRkIzd0swVTU0N2JMM2VoWmZCMTNHS002cEppR2VtZEVyWWdHakxMcUd1VXF4MApSQUpCREhrVmI5ZElWcDdZUVErejhqSGN0bXZ4Q2VldjMzVnEvYjdWM1drZ2ptWmZpUE1UdzBubHlNcFp6b01jCjN5QTRUK01UazlROXgvdGpoZFpkRkpCTXlVVkM0MVRtNXJmQjdMbWhhT3ZWR3lqTXZNd0hsUHFpU2NBVUdWV3kKUWlzRXcwYzVkSEJucklza0hncmtoam9kVmhqemx1TDAxaUEwdnQxNUw3YldTdTNGQ2FOQ20vUEV2Wm50V2dVbgp6aXUyU041Sk9WMGp3enIxS0IwM0ZtK1RteFZPZUNkajRkNGJIalptMWovcE12QkJUTUxOWlFad1FLWUtWVjlICmR6cnJBelZ2V2daMXdZK0IrUDByV04zWkxkWVM0Zkt1RkQ1N3I1WWxmV2dwMFV1N1ZnTW0yYVJOcnIyc2svL2oKZTA4WDJMalNQNlNrMm5OTkhhR3dIYmRvVnZMVnVXdFNzOHdKOVZVV1VyZWpxalpVRTNKL0FWUEtlZVZlaElkQQpmc1RYdzRzZ011Um5QMDNOTTlDU0F6Rkp4K0l1RmVjV28vcmMrTTloUk1qdDY2M01VQm9PY2hrd3l5S0dhcjBrCkpCaTFKMVN4eEpiTjg5UzZtK3g5TklCMm5pUVF0RmI2bjBxQllQSlhyZEpGem1XcXlKVWtiK1JyUDUvODFzczAKVkFrcWpCZHN5RTBQdXJUVXhmL2xGQ3o3VURURTlvY1NST3JudWVPRTJBWWJ1S2VtSnIzRHYzN2dESEtlT0VLUAo3T3JEUTg2ekptaz0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
    client-key-data: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUpRZ0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQ1N3d2dna29BZ0VBQW9JQ0FRRFQvdkxBMzdzSWRtM3YKRzhVbDRCWm12dEUyc0M1cm1zWFhlZmsyMml2TGxaR1VHM1dTOVljbUM2aU01YUFINXNNQmNXSEI4VUJEVngxagp1MUhHL1lHcjRJTkFzQ2w0YnlJd1l4Y2hia0V4TnptNXIxK01ESzJIMklHVnh0Uytidm5hR3h6SW93OXlQSGNxCmVoc3JjVUNGbytUN1h0V0JGS0FWbWM1cXhCOVFPaytwRUJlNzNPbml1Z05JNlJuc2k1UWQxcE1iVjBidUpUblQKbXp0S0c0eHgveUgvWUhoUHNnb1F6OXB6cVV2YzhWQXR4WUlMUkRUTFFJZmNCenVJSDg3RGhjVVN0L01UVFhmZwpmV0NwVzZ5QlBEOTVZN0NJSjZtUzRzSzloZzdvOHUyN3Z5L3RGUEJRejd1ampZNk81YjVGY3EyRGVCN2FUVTZmCjJVOXRXeXNsallCblc3MmxFN2pUR2pWaG5Jdkc1N1ZGYnRKZWdyVVo3bXFTRkxmdkJHYUtzNVFLUkwvU1FNTmkKZlJYelVFdWZka0ZzaHhWY3JIUW16TVpSS2NEaE5WTFJqRVhCa3hmaVJZaU5ueU5PR1oxTzMwQlpPdkRuRWxmKwoybkw0cHh0T3ZrVjFYektVYVJFQ1Q2bHFVN2tqWW9oQ3RoYnMrV1F4Nm8xdDhmSFIydXlmdWFuYXBpYzU2RTdrCkQySVI0a1FNcW54RUdZV1BLVFc0WTIzZmhaMFpoc05KYjYxWDlnTS9qOGRXT3lTaG04YUZiWENZZTBZcUJwTzgKaUE4enhEM2VESG5pd3c5b1Z5d0h2TFRrQlBYNEM4NWV0NEQxdkVUZnF1czROTVNqNFRTekpDRkM5QkRJRTZneQpaZy9HaEx0ci8xajZ1VDBXeFp6d3ZpMmVlMDJ3K1FJREFRQUJBb0lDQURBTlh1cjNDNGI4aVNpa3E4aE5CZWJlCkk3LzRxVno4cFJHVmRUYkl0eHFiV1hjdnpqTzBjYURmRGFKNlBnN3NjSkU0S1FkejdyUVUzL1dHTlNBY3dESzgKWGlQZ2lsWGhJdWZDM2pCV3RISTZhVnc4Y3pUa2ZzVUcvMEI2NUNnU01aSU5pVFcxT0VBVmtwRlBRaTlUcVdOaApaZnJRWVNhMERTRTRUc0NHbWU1dWVUWUNEczhuWU9CaWQzSWtYQnJ3L0c3Uy8xODRKankrdFYvUWxOelVaNzVECkxXcWNiRWpzT3puYVUxTGFNZmJ2djlQUUxBenZ0ZVBJU2NORzVHaVRoU051ZytBZFQveTFGNUlMK1VnS0hvemcKb2lhYXdSM3JsNVZTenY5MGpwYWcwZUEza3Q1elc1R0Z0S3Q2MzdCbVJQMnE0OGVrQjZKRjJhZUQ4MnYvT1VVTQoyR1JadDYrdXhHeWkxblRWSTA2YjZQVDFPQU5zSGZ4OUtvcTBybEdUQnY5TnFYcUtrczBldWRBUmFPUTB3UmFUCityaXA2MFhpalNFRkg2RzFlQXE3UnkvdUtTc0UzbnEwdGs3d2lWbFYwemlleVk2cjFUZnFXZjgvKzBxYndyZDIKalpVemp6UHUwSmJCZGRTeHJVUUpwcTcvSlliMjNKb0dnUVJPaTFQMUhKbjBqUVZXUkdPRUMzK2JKTitvamYzTQorSnhKUndidFNaYUphbnpMckpKbTF2MUFQMENqeENiM2N1b2lnc2JwL2RzOWF4YnFLaTduaVpvZjUwZUJSei9qCmQ3ZkJ1Sm9yQ09sbEpmM2p5ZHpXWTVqY1BSNjYyemczc2IyWUlnc2dacDJTaytCVTM0bXVCc0hsUUx6elFxRXgKc1RlQmNsd3BrQlNaODVoSzRkWjlBb0lCQVFEOUJRbGJjMUNPOFZLaFI0KzdtalJPTTMyMVNxdVlneEkveWFBWgpNUThIWEFaV1Uya084QnZ2bjZDdHI5SHlXQ005U1ZlQWEyNzdzQ1dSTkkxRGVoR0ZPekpJTUFOcDEzaGgva3lICkN3NzY4NTY0MHBtVlh3d1lSejBIN2FuUXJudHpaQ2YwV0lwWE5pd01CNnZvNkh3a1Z5M25LdDRTTWVRY2Y2bVoKYU1saHBrdlM1c3NkU25zUmRPUWZiZGhmdHF4ZXp6dlQ4WmcxNnFTeHM3b3IraytUVjlBbmZqL21HMnV3RHdLWApQb2Q5R3JUdTlJaXBuOFBvZ1Qza01xTzNCUUdJVml4V200cHc3T3dLOUhsYzNpcGR6eUV1YVcyREM0OGRyNm4zCk9lMDZ0ODJGRGZRZHZra0hUN3g2eU9aalBiRXBMNjNSYkpjVktRVFBpb1lFK1JmakFvSUJBUURXZmpVUi9QOWwKVTZjb0VhZEkrbmdvK3pVOU1WQ1VZazZnK3J1U3cvWml2ZTFBY1RUdXlZZmRQMGc1eDlDbkRLeXVhSlpEc0JXSgpiQUNCS2N6RjNYcHBoZ1BJRXA3WkFVYy9KdHZlWUNWYVlqczQ2cnZIbitNNHd2U3gvZ1JKSDhFZnZwVG1Bc1V3CktMMGFVRWVSWnFnTjZMREJRNnVRWFppR3hyd1pRdFZhTVlzVVpXSDAwTzFja0d0Mk5jUWdlOXh0YVZwV3BwY2MKWGxSYWRSK0JXaXFvSTJLdllwK1ZpU3VEQ3FnN0gwWlBVeGY1RHgvcEVYd3l0WDRkUjdaSVdvaEVoV2R2b25NLwp3VEhTSUZHc0ZBQlhVdEUrbkRHNjhJQzh3ejdNR2dEbW1adW5KbXZUN2RnMEQ0ZmtwZnQ2NHlQRHFiZ2VrUnE0CmtNUnFiL28rZmhKekFvSUJBQ1daZVFHQkNtaWpqZjd2am5sM2VleGhGSDQ3WVhLaGo3V3c5Ynlvb0s0Y1M4aksKVG1OczVRbmY4OVc3dWZ4RWdzQVp4UW9OYlFtejdIRSttUHQ5Q1Z0K0o0TzR0dGtrcnZ3SStVQmNNVmF6bTFPbAo0RExsVS92TG9sTXFTMEQ2bk5mUisyb0JPbFdwZERRNWM1K0I1T2pWbDdteGtoeXNFMVQwMTdRM2NTMjBzN0hjCm9EUnpIQVRGRlIxaWluUDJ4bmkwWFJTcTQwNm4xdCtkY0w0V1RYcjg0cTdyd1AwbCtBUEt4enpJaXdQWlV5ZnIKYU4ra0lVM00zdkNwWWREUnlwK0RCc1c4Q1grc2hZcy9OMFhJc2cwTXVjYVczakpLSm5ObjVsOFoyWm9QTkZoZwpjWFYyRUk0b21ENjYyaG5IVWl0bnJYSGdyRGIxeUlRNjlwMklrcmNDZ2dFQUdRT3c5cjhWbmVDS252Nm9EcmUvCktiQmFQaCt4TVF6aDlKNHBIKzJnbjFWZEJPWHU4V1lwWlNFTE1FbmdTSXNPM0d3d0VnYklERFcvUFZEOW81bTMKdS9TNEhpNGx2bE1LMXcrV0ZySUp5U2VwbG5LeG9ZOUE5WTZ1OE04Wit0a3NNYUtOUk9IUDAxVDg4TU9xQlFmKwowMWh1dkt0Q3A5eHlmRTFUQkhNcDVKSGdrV2xkYWlxdmM5c1gzVHBaL0J2VjBpQzJPMkxFUHJlMWlMTWVFSHpPCmVydGR0K3g5aGZmd1RpRUJDNXdUSEE4cHZZOEkvcXBlWEorVDdLQS9YdUxILzQyN1NXYWRvRExNdDUrelJxa3kKZlB5WWtIK3d3UWRwVEJwTkNZcUN6bUhkcURtdjI1QmlaWGZtTmtFeE9keWhnQ0ViNnR5clRCajkveGUrREdteApod0tDQVFFQWlxa2lHTUtBZms2cG5lelNiZUdjVis3bjNyQlB1TXJoTHVyRkNtMllpL1BSOTE1YXlLdWtYdnpVCnNleld5eFY1cUJIblZYdnNpblRYT212THBnVEovdWdzREdRQ3h2bVNaZXNqWkpNcE1VUnUvZmswS2pVK0RqZVgKeFVGZ3p5NVpiVjZlSXlwWmE4OUZqK2RYVnJqWTZsNXVnWjdhZHNJUnN5WkFMQnQwRjNaZ200REFBRWo5RWtMdgpZZjJlbUdwTGpOVE9FOTdlOXNMNC9LWEZ3UmdZbm5kc1hMdVNPQ29DWnBDTG56VENWMTdYeTR5MHlTZ3ZaTUxUCjIxaTI3WVAvNlc0WDUvNmFGVVhIOUFhaHJOMzB2MnpMVmRLeXJHQUk4amtJeHJDWW05UjBLOWR1RGdtYXNRRWYKaC9ka2dDM0x3WHB2djUyTG1rbUtZL09nTUh3OW13PT0KLS0tLS1FTkQgUFJJVkFURSBLRVktLS0tLQo=
    
    
root@jumpbox:~/kubernetes-the-hard-way# kubectl config set-credentials system:node:node-1 \
  --client-certificate=node-1.crt \
  --client-key=node-1.key \
  --embed-certs=true \
  --kubeconfig=node-1.kubeconfig && cat node-1.kubeconfig
  
  
# set-context : default 추가
root@jumpbox:~/kubernetes-the-hard-way# kubectl config set-context default \
  --cluster=kubernetes-the-hard-way \
  --user=system:node:node-0 \
  --kubeconfig=node-0.kubeconfig && cat node-0.kubeconfig
Context "default" created.
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUZURENDQXpTZ0F3SUJBZ0lVY1NNVHR5S29XcXlkK1lYWUZqVVZhd05pT2prd0RRWUpLb1pJaHZjTkFRRU4KQlFBd1FURUxNQWtHQTFVRUJoTUNWVk14RXpBUkJnTlZCQWdNQ2xkaGMyaHBibWQwYjI0eEVEQU9CZ05WQkFjTQpCMU5sWVhSMGJHVXhDekFKQmdOVkJBTU1Ba05CTUI0WERUSTJNREV4TURJeU1EVTFObG9YRFRNMk1ERXhNVEl5Ck1EVTFObG93UVRFTE1Ba0dBMVVFQmhNQ1ZWTXhFekFSQmdOVkJBZ01DbGRoYzJocGJtZDBiMjR4RURBT0JnTlYKQkFjTUIxTmxZWFIwYkdVeEN6QUpCZ05WQkFNTUFrTkJNSUlDSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQWc4QQpNSUlDQ2dLQ0FnRUFudE4xUGh0Q3lCZ0dYUnBWeHViaUp6emhTOStVUUpiUEgxeWd4WTNrOVVlQmZnV1YvSmxRCjBmWk1ib294aXMyYzVBR1B1SnpZbW9UbkZtZjNxRWdVY09Rc0ZVYlNGSWtSU1FOQW9JMmRUdk1ESUVLNXgrK3gKazZxN1luaVhHWFFEN3R3QUdON2dvdGt4NjNGSDBPbEJNb0tBR05QcTBNZHFGMEVacktxdXlUQ1paU09yRHNjawo2bysycGxJNWVlTmg1YzBFaUFFTmxZdFc5UVd5enJDOFZLOWNYR0hDU1hqemhUc05KQUY2a0ZvNWFUTWZtRjdDCnhBTFRqSlFpc0o0VkpZdytHdVRkS2FnME00b0svTXQySkxlcElJeGl4dCtQTUpGNWdLeGpVdDVUMmE4emZ1NkwKQlQ5UEs3VGQydWd1TEdGTzh1dEJhT0U4T0NZYzZmMGdscVJ0ZHJHSUF6dXZBNk9LZlJYMGdQQ2N4bzY3UVRQeQpMdENaRUVlWnlvV3ZoRVNRVUxuYzNINVBzVzkwMndvdEU0L0ovRzIwNzhkNlhUZzRWNS9wUzhUNDQ5Q20yZXd1Cld5bzZNc1FZMllWbUdIdzBxTDhMZ2dDRDlNVHF2QTFoWVBzOGo0NjZxUldic01nNTFoRmxXazZ5b081RS9INXcKVUhuQlQrTHVWb3RpOXBRNC9oWjg3aDZNc0NsT3lDK2xFM0ZJMlkvU0FwamZXS0Y5dHVJaHhmY3J3dW5wcnUrTAorZFY5eDZ5em45SS9xQjhadmFLeTFuS0g2RU53RG5PN2llN0YrNTFnb2FacTBFV2UrSHg1ZzJFcHUwZlArdlBPCnUrSzB5bUxCaVhhVGJBS0NTTW9vNFpab3BRQjBBTVVrb3NzNkgxYzZSRjV3bDZabFlreXcrWkVDQXdFQUFhTTgKTURvd0RBWURWUjBUQkFVd0F3RUIvekFMQmdOVkhROEVCQU1DQVFZd0hRWURWUjBPQkJZRUZKN05Ocm9pYTBPbgoyeU1wbDFNYjBYTGZiV0hTTUEwR0NTcUdTSWIzRFFFQkRRVUFBNElDQVFCd3ByOCs4bmlHRTlVakFLUUcyQU5rCnh6SG5NUFFOeU44NXpFcXJCMFp4M2tpSEJ0RS9GaHpRdHhoL0lkZnozRTN0U0k4blRNbTRsSDYycnZQdmM1NEYKMTlLMWdXV3poeExrWkMrdEsyMEpVVVN5dVJkS0VlTzZTSHB0UVlwOEZkTWVhWVlMSS9jSHVBcmRTNkw5ek1pYQpCTDRZWEdwbTFxM3lYeVRrd3VnSFJTcFlxeUJ6UDhMa3NESjU3T2EyYSs3Q0xaYXU1ZnczSkpPRFJEc3V5OXRUClhGS2UzT2VWQS9INmcvQUMwUzlKa1JDTnVKODhxOG40S0hDRTRySzA2dUErVklUaHltd1p0dHlsTkhDQUVGNncKa2ptbjQ1SndIS3ZSY2YybTVhZDlVNWNWd0p5bkJidnZXNi9lMXFOVGgyZnRvcEUvUVVraHozUk8vNWlMQ3BIQgpNUjZWZW5qY05FYTg2TnoyUTVWOFRmLzhSWHpOWjZHU1BBQXhsUENTNDNkWkpMZVZUc2N2bTBURlZzRm5kQktxCmlOWXZjUGxyWHp0diswTVJxOXpkVWpQS1g2by85L2RBOXkxZG9GQlBRMWFxRWhnUGRWQnJqenJNbjdXaUVna2cKZWF4VlZaYnovbXNxYUF1akZnRUdaZ2V5OEFWUEI3WWNKSit5dXFSV2xMbmJ0enl2MUt6WGd1SytYYjZBazRFdAp5T2pscWhINlNKNm9JODA3MldwcXp5Z2hEcG9IOWt5VGpILy8xSEVLNVZOdXUxbUYxMGVrd05VQk9wQkREdXl5CjNDS20xUmhkUHlYRjhtSUxwOU9FODBrb3E1SzZ0RndOUy9oREVSdFFXdC9zMUN2dHFLa1NxZFlSVUlzKzBzcXQKWVRCZTJIdWJZVGptaUdOMzhOZnlOQT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
    server: https://server.kubernetes.local:6443
  name: kubernetes-the-hard-way
contexts:
- context:
    cluster: kubernetes-the-hard-way
    user: system:node:node-0
  name: default
current-context: ""
kind: Config
preferences: {}
users:
- name: system:node:node-0
  user:
    client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUdCRENDQSt5Z0F3SUJBZ0lVS3dQM3VtUHBKc2lsd1ovZGk5amZUS3BXOVhBd0RRWUpLb1pJaHZjTkFRRUwKQlFBd1FURUxNQWtHQTFVRUJoTUNWVk14RXpBUkJnTlZCQWdNQ2xkaGMyaHBibWQwYjI0eEVEQU9CZ05WQkFjTQpCMU5sWVhSMGJHVXhDekFKQmdOVkJBTU1Ba05CTUI0WERUSTJNREV4TURJeU1qZzBPRm9YRFRNMk1ERXhNVEl5Ck1qZzBPRm93YURFYk1Ca0dBMVVFQXd3U2MzbHpkR1Z0T201dlpHVTZibTlrWlMwd01SVXdFd1lEVlFRS0RBeHoKZVhOMFpXMDZibTlrWlhNeEN6QUpCZ05WQkFZVEFsVlRNUk13RVFZRFZRUUlEQXBYWVhOb2FXNW5kRzl1TVJBdwpEZ1lEVlFRSERBZFRaV0YwZEd4bE1JSUNJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBZzhBTUlJQ0NnS0NBZ0VBCjAvN3l3Tis3Q0hadDd4dkZKZUFXWnI3Uk5yQXVhNXJGMTNuNU50b3J5NVdSbEJ0MWt2V0hKZ3Vvak9XZ0IrYkQKQVhGaHdmRkFRMWNkWTd0Unh2MkJxK0NEUUxBcGVHOGlNR01YSVc1Qk1UYzV1YTlmakF5dGg5aUJsY2JVdm03NQoyaHNjeUtNUGNqeDNLbm9iSzNGQWhhUGsrMTdWZ1JTZ0Zabk9hc1FmVURwUHFSQVh1OXpwNHJvRFNPa1o3SXVVCkhkYVRHMWRHN2lVNTA1czdTaHVNY2Y4aC8yQjRUN0lLRU0vYWM2bEwzUEZRTGNXQ0MwUTB5MENIM0FjN2lCL08KdzRYRkVyZnpFMDEzNEgxZ3FWdXNnVHcvZVdPd2lDZXBrdUxDdllZTzZQTHR1Nzh2N1JUd1VNKzdvNDJPanVXKwpSWEt0ZzNnZTJrMU9uOWxQYlZzckpZMkFaMXU5cFJPNDB4bzFZWnlMeHVlMVJXN1NYb0sxR2U1cWtoUzM3d1JtCmlyT1VDa1MvMGtERFluMFY4MUJMbjNaQmJJY1ZYS3gwSnN6R1VTbkE0VFZTMFl4RndaTVg0a1dJalo4alRobWQKVHQ5QVdUcnc1eEpYL3RweStLY2JUcjVGZFY4eWxHa1JBaytwYWxPNUkyS0lRcllXN1Bsa01lcU5iZkh4MGRycwpuN21wMnFZbk9laE81QTlpRWVKRURLcDhSQm1GanlrMXVHTnQzNFdkR1liRFNXK3RWL1lEUDQvSFZqc2tvWnZHCmhXMXdtSHRHS2dhVHZJZ1BNOFE5M2d4NTRzTVBhRmNzQjd5MDVBVDErQXZPWHJlQTlieEUzNnJyT0RURW8rRTAKc3lRaFF2UVF5Qk9vTW1ZUHhvUzdhLzlZK3JrOUZzV2M4TDR0bm50TnNQa0NBd0VBQWFPQnpEQ0J5VEFKQmdOVgpIUk1FQWpBQU1CMEdBMVVkSlFRV01CUUdDQ3NHQVFVRkJ3TUNCZ2dyQmdFRkJRY0RBVEFPQmdOVkhROEJBZjhFCkJBTUNCYUF3RVFZSllJWklBWWI0UWdFQkJBUURBZ2VBTUNFR0NXQ0dTQUdHK0VJQkRRUVVGaEpPYjJSbExUQWcKUTJWeWRHbG1hV05oZEdVd0Z3WURWUjBSQkJBd0RvSUdibTlrWlMwd2h3Ui9BQUFCTUIwR0ExVWREZ1FXQkJUdwpkWXhHVWxkWHY4TTJUc3VTSzAzeE10ZHA0REFmQmdOVkhTTUVHREFXZ0JTZXpUYTZJbXREcDlzaktaZFRHOUZ5CjMyMWgwakFOQmdrcWhraUc5dzBCQVFzRkFBT0NBZ0VBRmhYZlYzV3diVzZOTlZMV1F3ZGh6Zk1BWU5KcUhZSGEKVlpna2lNN0NXVUlMc1lPbjNuRkIzd0swVTU0N2JMM2VoWmZCMTNHS002cEppR2VtZEVyWWdHakxMcUd1VXF4MApSQUpCREhrVmI5ZElWcDdZUVErejhqSGN0bXZ4Q2VldjMzVnEvYjdWM1drZ2ptWmZpUE1UdzBubHlNcFp6b01jCjN5QTRUK01UazlROXgvdGpoZFpkRkpCTXlVVkM0MVRtNXJmQjdMbWhhT3ZWR3lqTXZNd0hsUHFpU2NBVUdWV3kKUWlzRXcwYzVkSEJucklza0hncmtoam9kVmhqemx1TDAxaUEwdnQxNUw3YldTdTNGQ2FOQ20vUEV2Wm50V2dVbgp6aXUyU041Sk9WMGp3enIxS0IwM0ZtK1RteFZPZUNkajRkNGJIalptMWovcE12QkJUTUxOWlFad1FLWUtWVjlICmR6cnJBelZ2V2daMXdZK0IrUDByV04zWkxkWVM0Zkt1RkQ1N3I1WWxmV2dwMFV1N1ZnTW0yYVJOcnIyc2svL2oKZTA4WDJMalNQNlNrMm5OTkhhR3dIYmRvVnZMVnVXdFNzOHdKOVZVV1VyZWpxalpVRTNKL0FWUEtlZVZlaElkQQpmc1RYdzRzZ011Um5QMDNOTTlDU0F6Rkp4K0l1RmVjV28vcmMrTTloUk1qdDY2M01VQm9PY2hrd3l5S0dhcjBrCkpCaTFKMVN4eEpiTjg5UzZtK3g5TklCMm5pUVF0RmI2bjBxQllQSlhyZEpGem1XcXlKVWtiK1JyUDUvODFzczAKVkFrcWpCZHN5RTBQdXJUVXhmL2xGQ3o3VURURTlvY1NST3JudWVPRTJBWWJ1S2VtSnIzRHYzN2dESEtlT0VLUAo3T3JEUTg2ekptaz0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
    client-key-data: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUpRZ0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQ1N3d2dna29BZ0VBQW9JQ0FRRFQvdkxBMzdzSWRtM3YKRzhVbDRCWm12dEUyc0M1cm1zWFhlZmsyMml2TGxaR1VHM1dTOVljbUM2aU01YUFINXNNQmNXSEI4VUJEVngxagp1MUhHL1lHcjRJTkFzQ2w0YnlJd1l4Y2hia0V4TnptNXIxK01ESzJIMklHVnh0Uytidm5hR3h6SW93OXlQSGNxCmVoc3JjVUNGbytUN1h0V0JGS0FWbWM1cXhCOVFPaytwRUJlNzNPbml1Z05JNlJuc2k1UWQxcE1iVjBidUpUblQKbXp0S0c0eHgveUgvWUhoUHNnb1F6OXB6cVV2YzhWQXR4WUlMUkRUTFFJZmNCenVJSDg3RGhjVVN0L01UVFhmZwpmV0NwVzZ5QlBEOTVZN0NJSjZtUzRzSzloZzdvOHUyN3Z5L3RGUEJRejd1ampZNk81YjVGY3EyRGVCN2FUVTZmCjJVOXRXeXNsallCblc3MmxFN2pUR2pWaG5Jdkc1N1ZGYnRKZWdyVVo3bXFTRkxmdkJHYUtzNVFLUkwvU1FNTmkKZlJYelVFdWZka0ZzaHhWY3JIUW16TVpSS2NEaE5WTFJqRVhCa3hmaVJZaU5ueU5PR1oxTzMwQlpPdkRuRWxmKwoybkw0cHh0T3ZrVjFYektVYVJFQ1Q2bHFVN2tqWW9oQ3RoYnMrV1F4Nm8xdDhmSFIydXlmdWFuYXBpYzU2RTdrCkQySVI0a1FNcW54RUdZV1BLVFc0WTIzZmhaMFpoc05KYjYxWDlnTS9qOGRXT3lTaG04YUZiWENZZTBZcUJwTzgKaUE4enhEM2VESG5pd3c5b1Z5d0h2TFRrQlBYNEM4NWV0NEQxdkVUZnF1czROTVNqNFRTekpDRkM5QkRJRTZneQpaZy9HaEx0ci8xajZ1VDBXeFp6d3ZpMmVlMDJ3K1FJREFRQUJBb0lDQURBTlh1cjNDNGI4aVNpa3E4aE5CZWJlCkk3LzRxVno4cFJHVmRUYkl0eHFiV1hjdnpqTzBjYURmRGFKNlBnN3NjSkU0S1FkejdyUVUzL1dHTlNBY3dESzgKWGlQZ2lsWGhJdWZDM2pCV3RISTZhVnc4Y3pUa2ZzVUcvMEI2NUNnU01aSU5pVFcxT0VBVmtwRlBRaTlUcVdOaApaZnJRWVNhMERTRTRUc0NHbWU1dWVUWUNEczhuWU9CaWQzSWtYQnJ3L0c3Uy8xODRKankrdFYvUWxOelVaNzVECkxXcWNiRWpzT3puYVUxTGFNZmJ2djlQUUxBenZ0ZVBJU2NORzVHaVRoU051ZytBZFQveTFGNUlMK1VnS0hvemcKb2lhYXdSM3JsNVZTenY5MGpwYWcwZUEza3Q1elc1R0Z0S3Q2MzdCbVJQMnE0OGVrQjZKRjJhZUQ4MnYvT1VVTQoyR1JadDYrdXhHeWkxblRWSTA2YjZQVDFPQU5zSGZ4OUtvcTBybEdUQnY5TnFYcUtrczBldWRBUmFPUTB3UmFUCityaXA2MFhpalNFRkg2RzFlQXE3UnkvdUtTc0UzbnEwdGs3d2lWbFYwemlleVk2cjFUZnFXZjgvKzBxYndyZDIKalpVemp6UHUwSmJCZGRTeHJVUUpwcTcvSlliMjNKb0dnUVJPaTFQMUhKbjBqUVZXUkdPRUMzK2JKTitvamYzTQorSnhKUndidFNaYUphbnpMckpKbTF2MUFQMENqeENiM2N1b2lnc2JwL2RzOWF4YnFLaTduaVpvZjUwZUJSei9qCmQ3ZkJ1Sm9yQ09sbEpmM2p5ZHpXWTVqY1BSNjYyemczc2IyWUlnc2dacDJTaytCVTM0bXVCc0hsUUx6elFxRXgKc1RlQmNsd3BrQlNaODVoSzRkWjlBb0lCQVFEOUJRbGJjMUNPOFZLaFI0KzdtalJPTTMyMVNxdVlneEkveWFBWgpNUThIWEFaV1Uya084QnZ2bjZDdHI5SHlXQ005U1ZlQWEyNzdzQ1dSTkkxRGVoR0ZPekpJTUFOcDEzaGgva3lICkN3NzY4NTY0MHBtVlh3d1lSejBIN2FuUXJudHpaQ2YwV0lwWE5pd01CNnZvNkh3a1Z5M25LdDRTTWVRY2Y2bVoKYU1saHBrdlM1c3NkU25zUmRPUWZiZGhmdHF4ZXp6dlQ4WmcxNnFTeHM3b3IraytUVjlBbmZqL21HMnV3RHdLWApQb2Q5R3JUdTlJaXBuOFBvZ1Qza01xTzNCUUdJVml4V200cHc3T3dLOUhsYzNpcGR6eUV1YVcyREM0OGRyNm4zCk9lMDZ0ODJGRGZRZHZra0hUN3g2eU9aalBiRXBMNjNSYkpjVktRVFBpb1lFK1JmakFvSUJBUURXZmpVUi9QOWwKVTZjb0VhZEkrbmdvK3pVOU1WQ1VZazZnK3J1U3cvWml2ZTFBY1RUdXlZZmRQMGc1eDlDbkRLeXVhSlpEc0JXSgpiQUNCS2N6RjNYcHBoZ1BJRXA3WkFVYy9KdHZlWUNWYVlqczQ2cnZIbitNNHd2U3gvZ1JKSDhFZnZwVG1Bc1V3CktMMGFVRWVSWnFnTjZMREJRNnVRWFppR3hyd1pRdFZhTVlzVVpXSDAwTzFja0d0Mk5jUWdlOXh0YVZwV3BwY2MKWGxSYWRSK0JXaXFvSTJLdllwK1ZpU3VEQ3FnN0gwWlBVeGY1RHgvcEVYd3l0WDRkUjdaSVdvaEVoV2R2b25NLwp3VEhTSUZHc0ZBQlhVdEUrbkRHNjhJQzh3ejdNR2dEbW1adW5KbXZUN2RnMEQ0ZmtwZnQ2NHlQRHFiZ2VrUnE0CmtNUnFiL28rZmhKekFvSUJBQ1daZVFHQkNtaWpqZjd2am5sM2VleGhGSDQ3WVhLaGo3V3c5Ynlvb0s0Y1M4aksKVG1OczVRbmY4OVc3dWZ4RWdzQVp4UW9OYlFtejdIRSttUHQ5Q1Z0K0o0TzR0dGtrcnZ3SStVQmNNVmF6bTFPbAo0RExsVS92TG9sTXFTMEQ2bk5mUisyb0JPbFdwZERRNWM1K0I1T2pWbDdteGtoeXNFMVQwMTdRM2NTMjBzN0hjCm9EUnpIQVRGRlIxaWluUDJ4bmkwWFJTcTQwNm4xdCtkY0w0V1RYcjg0cTdyd1AwbCtBUEt4enpJaXdQWlV5ZnIKYU4ra0lVM00zdkNwWWREUnlwK0RCc1c4Q1grc2hZcy9OMFhJc2cwTXVjYVczakpLSm5ObjVsOFoyWm9QTkZoZwpjWFYyRUk0b21ENjYyaG5IVWl0bnJYSGdyRGIxeUlRNjlwMklrcmNDZ2dFQUdRT3c5cjhWbmVDS252Nm9EcmUvCktiQmFQaCt4TVF6aDlKNHBIKzJnbjFWZEJPWHU4V1lwWlNFTE1FbmdTSXNPM0d3d0VnYklERFcvUFZEOW81bTMKdS9TNEhpNGx2bE1LMXcrV0ZySUp5U2VwbG5LeG9ZOUE5WTZ1OE04Wit0a3NNYUtOUk9IUDAxVDg4TU9xQlFmKwowMWh1dkt0Q3A5eHlmRTFUQkhNcDVKSGdrV2xkYWlxdmM5c1gzVHBaL0J2VjBpQzJPMkxFUHJlMWlMTWVFSHpPCmVydGR0K3g5aGZmd1RpRUJDNXdUSEE4cHZZOEkvcXBlWEorVDdLQS9YdUxILzQyN1NXYWRvRExNdDUrelJxa3kKZlB5WWtIK3d3UWRwVEJwTkNZcUN6bUhkcURtdjI1QmlaWGZtTmtFeE9keWhnQ0ViNnR5clRCajkveGUrREdteApod0tDQVFFQWlxa2lHTUtBZms2cG5lelNiZUdjVis3bjNyQlB1TXJoTHVyRkNtMllpL1BSOTE1YXlLdWtYdnpVCnNleld5eFY1cUJIblZYdnNpblRYT212THBnVEovdWdzREdRQ3h2bVNaZXNqWkpNcE1VUnUvZmswS2pVK0RqZVgKeFVGZ3p5NVpiVjZlSXlwWmE4OUZqK2RYVnJqWTZsNXVnWjdhZHNJUnN5WkFMQnQwRjNaZ200REFBRWo5RWtMdgpZZjJlbUdwTGpOVE9FOTdlOXNMNC9LWEZ3UmdZbm5kc1hMdVNPQ29DWnBDTG56VENWMTdYeTR5MHlTZ3ZaTUxUCjIxaTI3WVAvNlc0WDUvNmFGVVhIOUFhaHJOMzB2MnpMVmRLeXJHQUk4amtJeHJDWW05UjBLOWR1RGdtYXNRRWYKaC9ka2dDM0x3WHB2djUyTG1rbUtZL09nTUh3OW13PT0KLS0tLS1FTkQgUFJJVkFURSBLRVktLS0tLQo=
    
root@jumpbox:~/kubernetes-the-hard-way# kubectl config set-context default \
  --cluster=kubernetes-the-hard-way \
  --user=system:node:node-1 \
  --kubeconfig=node-1.kubeconfig && cat node-1.kubeconfig
  

# use-context : current-context 에 default 추가
root@jumpbox:~/kubernetes-the-hard-way# kubectl config use-context default \
  --kubeconfig=node-0.kubeconfig
Switched to context "default".
root@jumpbox:~/kubernetes-the-hard-way# kubectl config use-context default \
  --kubeconfig=node-1.kubeconfig
Switched to context "default".


root@jumpbox:~/kubernetes-the-hard-way# ls -l *.kubeconfig
-rw------- 1 root root 10161 Jan 11 07:49 node-0.kubeconfig
-rw------- 1 root root 10161 Jan 11 07:49 node-1.kubeconfig

 

동일한 방식으로 kube-proxy, kube-controller-manager, kube-scheduler, admin kubeconfig 파일 생성 후 나누겠습니다.

root@jumpbox:~/kubernetes-the-hard-way# kubectl config set-cluster kubernetes-the-hard-way \
  --certificate-authority=ca.crt \
  --embed-certs=true \
  --server=https://server.kubernetes.local:6443 \
  --kubeconfig=kube-proxy.kubeconfig
Cluster "kubernetes-the-hard-way" set.

root@jumpbox:~/kubernetes-the-hard-way# kubectl config set-credentials system:kube-proxy \
  --client-certificate=kube-proxy.crt \
  --client-key=kube-proxy.key \
  --embed-certs=true \
  --kubeconfig=kube-proxy.kubeconfig
User "system:kube-proxy" set.

root@jumpbox:~/kubernetes-the-hard-way# kubectl config set-context default \
  --cluster=kubernetes-the-hard-way \
  --user=system:kube-proxy \
  --kubeconfig=kube-proxy.kubeconfig
Context "default" created.

root@jumpbox:~/kubernetes-the-hard-way# kubectl config use-context default \
  --kubeconfig=kube-proxy.kubeconfig
Switched to context "default".

root@jumpbox:~/kubernetes-the-hard-way# cat kube-proxy.kubeconfig
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUZURENDQXpTZ0F3SUJBZ0lVY1NNVHR5S29XcXlkK1lYWUZqVVZhd05pT2prd0RRWUpLb1pJaHZjTkFRRU4KQlFBd1FURUxNQWtHQTFVRUJoTUNWVk14RXpBUkJnTlZCQWdNQ2xkaGMyaHBibWQwYjI0eEVEQU9CZ05WQkFjTQpCMU5sWVhSMGJHVXhDekFKQmdOVkJBTU1Ba05CTUI0WERUSTJNREV4TURJeU1EVTFObG9YRFRNMk1ERXhNVEl5Ck1EVTFObG93UVRFTE1Ba0dBMVVFQmhNQ1ZWTXhFekFSQmdOVkJBZ01DbGRoYzJocGJtZDBiMjR4RURBT0JnTlYKQkFjTUIxTmxZWFIwYkdVeEN6QUpCZ05WQkFNTUFrTkJNSUlDSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQWc4QQpNSUlDQ2dLQ0FnRUFudE4xUGh0Q3lCZ0dYUnBWeHViaUp6emhTOStVUUpiUEgxeWd4WTNrOVVlQmZnV1YvSmxRCjBmWk1ib294aXMyYzVBR1B1SnpZbW9UbkZtZjNxRWdVY09Rc0ZVYlNGSWtSU1FOQW9JMmRUdk1ESUVLNXgrK3gKazZxN1luaVhHWFFEN3R3QUdON2dvdGt4NjNGSDBPbEJNb0tBR05QcTBNZHFGMEVacktxdXlUQ1paU09yRHNjawo2bysycGxJNWVlTmg1YzBFaUFFTmxZdFc5UVd5enJDOFZLOWNYR0hDU1hqemhUc05KQUY2a0ZvNWFUTWZtRjdDCnhBTFRqSlFpc0o0VkpZdytHdVRkS2FnME00b0svTXQySkxlcElJeGl4dCtQTUpGNWdLeGpVdDVUMmE4emZ1NkwKQlQ5UEs3VGQydWd1TEdGTzh1dEJhT0U4T0NZYzZmMGdscVJ0ZHJHSUF6dXZBNk9LZlJYMGdQQ2N4bzY3UVRQeQpMdENaRUVlWnlvV3ZoRVNRVUxuYzNINVBzVzkwMndvdEU0L0ovRzIwNzhkNlhUZzRWNS9wUzhUNDQ5Q20yZXd1Cld5bzZNc1FZMllWbUdIdzBxTDhMZ2dDRDlNVHF2QTFoWVBzOGo0NjZxUldic01nNTFoRmxXazZ5b081RS9INXcKVUhuQlQrTHVWb3RpOXBRNC9oWjg3aDZNc0NsT3lDK2xFM0ZJMlkvU0FwamZXS0Y5dHVJaHhmY3J3dW5wcnUrTAorZFY5eDZ5em45SS9xQjhadmFLeTFuS0g2RU53RG5PN2llN0YrNTFnb2FacTBFV2UrSHg1ZzJFcHUwZlArdlBPCnUrSzB5bUxCaVhhVGJBS0NTTW9vNFpab3BRQjBBTVVrb3NzNkgxYzZSRjV3bDZabFlreXcrWkVDQXdFQUFhTTgKTURvd0RBWURWUjBUQkFVd0F3RUIvekFMQmdOVkhROEVCQU1DQVFZd0hRWURWUjBPQkJZRUZKN05Ocm9pYTBPbgoyeU1wbDFNYjBYTGZiV0hTTUEwR0NTcUdTSWIzRFFFQkRRVUFBNElDQVFCd3ByOCs4bmlHRTlVakFLUUcyQU5rCnh6SG5NUFFOeU44NXpFcXJCMFp4M2tpSEJ0RS9GaHpRdHhoL0lkZnozRTN0U0k4blRNbTRsSDYycnZQdmM1NEYKMTlLMWdXV3poeExrWkMrdEsyMEpVVVN5dVJkS0VlTzZTSHB0UVlwOEZkTWVhWVlMSS9jSHVBcmRTNkw5ek1pYQpCTDRZWEdwbTFxM3lYeVRrd3VnSFJTcFlxeUJ6UDhMa3NESjU3T2EyYSs3Q0xaYXU1ZnczSkpPRFJEc3V5OXRUClhGS2UzT2VWQS9INmcvQUMwUzlKa1JDTnVKODhxOG40S0hDRTRySzA2dUErVklUaHltd1p0dHlsTkhDQUVGNncKa2ptbjQ1SndIS3ZSY2YybTVhZDlVNWNWd0p5bkJidnZXNi9lMXFOVGgyZnRvcEUvUVVraHozUk8vNWlMQ3BIQgpNUjZWZW5qY05FYTg2TnoyUTVWOFRmLzhSWHpOWjZHU1BBQXhsUENTNDNkWkpMZVZUc2N2bTBURlZzRm5kQktxCmlOWXZjUGxyWHp0diswTVJxOXpkVWpQS1g2by85L2RBOXkxZG9GQlBRMWFxRWhnUGRWQnJqenJNbjdXaUVna2cKZWF4VlZaYnovbXNxYUF1akZnRUdaZ2V5OEFWUEI3WWNKSit5dXFSV2xMbmJ0enl2MUt6WGd1SytYYjZBazRFdAp5T2pscWhINlNKNm9JODA3MldwcXp5Z2hEcG9IOWt5VGpILy8xSEVLNVZOdXUxbUYxMGVrd05VQk9wQkREdXl5CjNDS20xUmhkUHlYRjhtSUxwOU9FODBrb3E1SzZ0RndOUy9oREVSdFFXdC9zMUN2dHFLa1NxZFlSVUlzKzBzcXQKWVRCZTJIdWJZVGptaUdOMzhOZnlOQT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
    server: https://server.kubernetes.local:6443
  name: kubernetes-the-hard-way
contexts:
- context:
    cluster: kubernetes-the-hard-way
    user: system:kube-proxy
  name: default
current-context: default
kind: Config
preferences: {}
users:
- name: system:kube-proxy
  user:
    client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUdFakNDQS9xZ0F3SUJBZ0lVS3dQM3VtUHBKc2lsd1ovZGk5amZUS3BXOVhJd0RRWUpLb1pJaHZjTkFRRUwKQlFBd1FURUxNQWtHQTFVRUJoTUNWVk14RXpBUkJnTlZCQWdNQ2xkaGMyaHBibWQwYjI0eEVEQU9CZ05WQkFjTQpCMU5sWVhSMGJHVXhDekFKQmdOVkJBTU1Ba05CTUI0WERUSTJNREV4TURJeU1qZzFNbG9YRFRNMk1ERXhNVEl5Ck1qZzFNbG93YmpFYU1CZ0dBMVVFQXd3UmMzbHpkR1Z0T210MVltVXRjSEp2ZUhreEhEQWFCZ05WQkFvTUUzTjUKYzNSbGJUcHViMlJsTFhCeWIzaHBaWEl4Q3pBSkJnTlZCQVlUQWxWVE1STXdFUVlEVlFRSURBcFhZWE5vYVc1bgpkRzl1TVJBd0RnWURWUVFIREFkVFpXRjBkR3hsTUlJQ0lqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FnOEFNSUlDCkNnS0NBZ0VBNEt1RGdrWVhrRzhaYVFhb2dmcnhCVFNOOXovZkhKdWxNalBBODRYL0ZHaTYzNFNMSEpSbUZybC8Kb2tzYXRjdGhBaWcwaXVlNW4wWHYwUzUxU2NhUlpHQk1NQ1dBOVVDRUdoOTRGVHZFemp4SkpnZHlLbjEreldHMAp0UFhIM2ROWFNHaWptYmpqWGI5Nmhndm0xMEN3WjZYMWVneksxTnRPUVRRVmR4emhUWUpkZjFYNU5VUERLZHo3CmdsZ1FvS2F2TW5LMmV0T2ZMTGpBamdncWsvaEZYbTloUXNCdDJDWHp6ZlF5Nkc1ZHR6OUJwSGxRT1liamJZNEEKU0grNUR4clk0MGd5dHM0TFdtNmU4bHZCditWUXhubTlJcUhFQ2Vvc3JkRENjWWx5bW9RNmpmY0JtN2dRYXFnUAptY0Q0T0ptVlVEdE1iZ2piTXBxOG4zZ1JrcXFLam9lQTN2d1BFYStvK0UvcHpYQy9udEZ5WEhzQjNsclNkOUNhClN6V2xmVkFyQWlSOVBQdHMwbjFqMCtzTFgxSytMYndQVUh0cjliRWVzV0RSbW9kODE0QXRsY3lPVVkvYlBqbHMKaEtENDF1Qk9ZcU0zVGJucHVQTjBkNDBtOEFJYXpGY0p6RFU4Vk5FLzU1ellIeHlXcEQ3dm5JclZHclVNYVA1NApPcUxKRE56Si9XQmhFcklrRFlEZ1lwSEFIL3RFcEZqc3pKM3BZZllBb2hBaDdIL0JYSHNGYmlPUmpZUnZTckw1CjJaQ3lUQkFpV1QrWEl3SE9aY2EySnhaNXRIejIzQ1EwWFYwaW9WRldldDIxZ0p4MWFKalFEN1RlbXVoT0RDTnEKQmQ0MDY5UjVqOEY2QW5oSjZvaDZIRFBtVGFtRHlOLzNtc2JaU0xUbk9McnUwQzFnS3EwQ0F3RUFBYU9CMURDQgowVEFKQmdOVkhSTUVBakFBTUIwR0ExVWRKUVFXTUJRR0NDc0dBUVVGQndNQ0JnZ3JCZ0VGQlFjREFUQU9CZ05WCkhROEJBZjhFQkFNQ0JhQXdFUVlKWUlaSUFZYjRRZ0VCQkFRREFnZUFNQ1VHQ1dDR1NBR0crRUlCRFFRWUZoWkwKZFdKbElGQnliM2g1SUVObGNuUnBabWxqWVhSbE1Cc0dBMVVkRVFRVU1CS0NDbXQxWW1VdGNISnZlSG1IQkg4QQpBQUV3SFFZRFZSME9CQllFRkw1OVR0eVN3S3E1YkVFZTFTK2l4aVo1OVdOU01COEdBMVVkSXdRWU1CYUFGSjdOCk5yb2lhME9uMnlNcGwxTWIwWExmYldIU01BMEdDU3FHU0liM0RRRUJDd1VBQTRJQ0FRQ05WRURkSlFsSlozNVYKVEM1UmJITExQTEk2SFJOeTVvUm9UUGFRazhPSWFWZTZULzR0Vk15bUNwZklVR1JxQVFqRkZDcVBua3R1QjBEKwpmd1RoL01xMDNYNDRwRTlwWmFEbVIzWk5qVVpkV045NjF2UnJSTTVaVzhzaDIrVk5CN2lpc2VHY3h1ZDN1TnEvCmlEdjV4d3BEQUZib1R5ZDE0VDFsT0NIbW45eFBTcDQ1aGtKWjhYT00yT1dJNTlINWZ0Y2lLNmdCd1Y4OWxMSHQKNGFyMmZ6VEdaR3hPOW04ZHRsbUxXaVg1S1U0VVlyVTN0OW5pUGV3a2g0VzhMM0FvVU1QSlZFa0F1VlNBZE81NgpBTHRibDdJbW5tZ3RRU1gvS0dheDVGdEl5TUhoMGZ0cFlCNFJGQnRBa0FXQ04zN04yNmJGWnB5TEdOVDE3MFArCkU2QTZoVjlWUVZDeXV1TzdSN3VUcFRDR1BmU1VxZGNJbVVDVUxlVUR5d3VnR1R4VTVwSFNiQ1VMTmdDU2FHcWcKeUtkV04vb3dicVY1Tkd6WWdtVnJ3RUV1WWtUYi9RS3h4SWF0UEEyRmFySlBSK2xBRFYyRXVid1V6ZzVJN21DUApjb040WXA1Y2N4ZzQ1bWNDOE5iN0J3OTJHREhYeUZoWGc4UWJuREVUWThwdmQzWWVhTXhCSHF6ZlM5S0lqa25aCkYzd29aQTcwWlVPQlkrMk1NcURRZzUxYnBaM0d6Zkk5L0IxVE92MHpTbXFLa2xpMmRDNHNzVGNyaTNTU3h0emQKY0VNMWlpdVBPaXN5YnVEMWhIeXpDYnVEU0MyZTdXMUU4UmttajRmQjhVVzF0NFYxdHJ3c3hINFd0UGdkMmJKWQpPcEkwR3FEeDU3TEduMFFXSms1OW9lRFFQU0ZEVEE9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
    client-key-data: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUpRd0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQ1Mwd2dna3BBZ0VBQW9JQ0FRRGdxNE9DUmhlUWJ4bHAKQnFpQit2RUZOSTMzUDk4Y202VXlNOER6aGY4VWFMcmZoSXNjbEdZV3VYK2lTeHExeTJFQ0tEU0s1N21mUmUvUgpMblZKeHBGa1lFd3dKWUQxUUlRYUgzZ1ZPOFRPUEVrbUIzSXFmWDdOWWJTMDljZmQwMWRJYUtPWnVPTmR2M3FHCkMrYlhRTEJucGZWNkRNclUyMDVCTkJWM0hPRk5nbDEvVmZrMVE4TXAzUHVDV0JDZ3BxOHljclo2MDU4c3VNQ08KQ0NxVCtFVmViMkZDd0czWUpmUE45RExvYmwyM1AwR2tlVkE1aHVOdGpnQklmN2tQR3RqalNESzJ6Z3RhYnA3eQpXOEcvNVZER2ViMGlvY1FKNml5dDBNSnhpWEthaERxTjl3R2J1QkJxcUErWndQZzRtWlZRTzB4dUNOc3ltcnlmCmVCR1Nxb3FPaDREZS9BOFJyNmo0VCtuTmNMK2UwWEpjZXdIZVd0SjMwSnBMTmFWOVVDc0NKSDA4KzJ6U2ZXUFQKNnd0ZlVyNHR2QTlRZTJ2MXNSNnhZTkdhaDN6WGdDMlZ6STVSajlzK09XeUVvUGpXNEU1aW96ZE51ZW00ODNSMwpqU2J3QWhyTVZ3bk1OVHhVMFQvbm5OZ2ZISmFrUHUrY2l0VWF0UXhvL25nNm9za00zTW45WUdFU3NpUU5nT0JpCmtjQWYrMFNrV096TW5lbGg5Z0NpRUNIc2Y4RmNld1Z1STVHTmhHOUtzdm5aa0xKTUVDSlpQNWNqQWM1bHhyWW4KRm5tMGZQYmNKRFJkWFNLaFVWWjYzYldBbkhWb21OQVB0TjZhNkU0TUkyb0YzalRyMUhtUHdYb0NlRW5xaUhvYwpNK1pOcVlQSTMvZWF4dGxJdE9jNHV1N1FMV0FxclFJREFRQUJBb0lDQUFjNS9SVG5wRUpsRUhBc1lxY3JweXovCnI4RlFNS0QrOEtWWXZOQVljMGY0eG1vQ0hXZGg3cGEwaU1Kem4veFErbUhUWVQxR2p0WHNyZllRaEgxSEFjNDAKdXI2aHRqQXRUeEo0Q0tqR0wySmkxZ2QvSGRENEVHZ1N5SGs1bnFBbitCckFJdU1DNjIxTWgyaGdZYUJ5MkRtOQpRTlFZTFQ0RGY5VGhFLytzMGlKb0d4SEpkaWFjYzE2WldRMnNQM3lyWDk5RGlWTVNFNENnd0xEUTJtM0FBcHN6CkFmSGZ0cWpKTDdwa0xHOEZmY1l6SnExZnFaRHdJY2lZVkxJQVNiZU9xWU5HQXp1V0RROXZsM1U4TmxNeDBSTlIKUHlBcUMrQTF4QklqTU4zdUNkMm1leXV0MGtOci9Ec3lCSzV4WW9xUGhobjZqazdMd2lFeWtQYWdLaENKbzhNNgpieGZMbGdnSFhhdSsrbkNvRVF6Q3VKdVZLV2IvOS9OTE1HUmlEYW1PcERtc2xFa2tZSHBhaVBFZ0p2amlpQzJsCnFSMXBEZitJb1YwdWFRMWlWdGJPY3RpeVhYclMrRkFEWVFnaXY2V1BVNnVWRTk2M1hqWk9kWCt1V0RUdGtuZ2MKSmJLejVWeThxQUl0dWlNQWFiZjR4dkdMRG1XSVJQbm9FY2JRZVZUaktOcG8wWkw2Q2kySlpOR0w1cnFqaXBPZwo3ZzhhOVRvREk0aWZYakRXeGd6MmkyNTNJMStML3lzR1hzVklCUnF0Wnl5dDVYejQ1d1BXL3IwMm9hQ21KR0RqCmhDWW5KVVhFUzdBM3ZpQS9OVWdFa1E5eE13cTVibEN3eVlRRlU5VGdiZ3NDWjkybkJNamh2REZZOWtzeUlDRWIKQmV4NjkvWkYwTS9IZFNSS1JwOFJBb0lCQVFENnE0eEQvaXhQbEVuSURWZkhaWFFkb0dDY0dyd09yL2tWR0R6Qgo3a0diK2dTZm5xMTF2NEthNWYzUVluQ1ZEQWVmK3dPL2Viaksvb2UwK2dFc1lXZEk0b0h1YjFHUkVEUk1wdElNCk54bkRuS1BWSUVRL2JadTJla3MydUVuYzNnNTdYbjNFSjNzSWIwU04wSDFYWDZRVkhaLzRkTVcvR3kvZ2dTTlAKbE1TZnRKRXZERFR5dGhCWHVkVm5HQk9qbGwzUlBuQzhHRkdOR1IyNlFoeisrNy9Zb2dvb1hFYlBrelFPQjRMYwpValY1YlI0ck9wWmJLQWR5SnFEbTJQc1F6RjBuSzFxaElFQ3g5ekFodmNwcWljcFhjU0NuRG9WS25pdXdJdEZmCm5OYWNnMXQ4S0JGZmRzaG4vdVFOYjgyQjZXZWJ5WC8yeWc4TkZyNWY5YXc0ejd3SEFvSUJBUURsY25EL1FJeFAKVzdZNVl3L1UzVGxOcEljU1JsTXhpNEs1SGdwRTFXWHR5QWFtb3BvZzdSb1ZsVEhJRVQ4eUpyWW8zQkE4UXMzVApFbGRjWkFMWGI5S3JyVTUvbmlCOHRrWXltSlI5ZDJEdzAyVlZNenlUb2MwQlFGbUlldUd0ejdtbmVPMFlMWXhOClZ0bTlZZVYzNCtNekxueVNZalFYSjluSGlYRm5scnBWcFlGZERYdXJYM2VnWFJZUTRKTWNSUGJzaEJmQVFpRmUKQjV0TXllMEVqTThVKzFBOURLR2ZKL3kyTjF3eDVsR01TQ3B1NzkvcHIvNWp5c001K0VBQ0pNaldpSkNxR3dwegplZkprdXYzdFBjNmJsOFNFaGtIRGMySkNidkNnbmFUNWJjVjJDSlZzRkxsaGNaMkpIaEpSOG1XOXZYZDhkQjFECjIzVDZyZUNCRlY2ckFvSUJBUUN5cTc0aDVMUyswRXE2emsvbjczZVJlblFDTU1na2krZTEwbjNVR1Rnb3JrL0gKV25uM09OY21BNU1qaWxjRzFmbEZYY3p4R1JqUGtCYzR0dzVKRFBCcXNoQzgzQm0rbFZkQjM1Sk9aS1AzbXRubwpHc1NxbFR6dEYwUXZMN0p1UE5VRHVIbGFiRzIwdUdLYjFxVFF0M29rRnVha1dNOXVoVGxlQTQ0Z3RrQmtPWGRXCm1wUFBBRmlydnVqT1FBb1hpeUU1K1JDdjhZR0hXZ1NuYzJKcG1SWEltczgwcjNsRmtYNEVGZlIvaUJWWGhLQ0IKWFpRNFMxTHJXWDlNckJKZ2lkcElCZzNtVlMvbjZmSWp5cnpSclg5TlRuUmd2dWZoSk5hdENGUkdtMnNaU2tQVwpQbFVMdjRYZkluNTQyVjBaSVQzWmZBbTY1WkZPMmd3K0o4Vm5CU0xYQW9JQkFRQ3Y5amdhU1JKUnVlL2h5c3JWCllHTVYzRnVKOUV6UTdrRHVYczlaUXA3TTRGM1paVkgyZGw5T3RnQmJnbjZJbzQrSGZsMGxHY1puWE9XS2dWaDgKaDlGMHY1QTM1cmpiYTU0aUowbVpmdmZsT1BtNWdYV3ZjcUtabHhRU3lzcFFWY0gzWVpIU3ZQdWdSRDd3TWllYwo3alBMaUpjWVhCKytzbDBkM1pZTzcxVXZZYUg0RHVNTTVrWUR3ZCt1U2N3SUhndVFEeTEzMEQ5dXNUNjBnUmM0CktoU1Y3clgyVzcySEpVOTFIcmVodlJSRkZRTVYyUGhMYXlFWXZ1TkJqZFRvei9VR01lMWZ4eVVZc2lqbWYxRkYKbytUVEJtMDdoUXJpTFpicGc5TWVHa2Z1MGZSaE5Pd0MyMUhnSFJYSGxqeE9oQ3JxZkdjcUZwSnErOTZXY01wLwp0RGZKQW9JQkFIWUYxa01kL0I2cUdlVEsxaTlBK3dQQ3AzQXhWTWxjWTVSbVFsWTIvcXRyN3plYVNqTlorUisrCk96OGNBVWFHUkxOVzRiNVkzU3NTaDhVNEZUUGZDN3d3RXJDcnl2SEdMbzcxTlZwdEVRQkFza3BkQkw4VFBHQ2cKMWhSbG0zTWlsSmhGYmxNalp0QVVLWGdsajlaSklZcW9ZRTY2NWlIeHV2ZGdmT2RaU2RoMzhHL3ptODB5czRWZQpRWnNhRjJ5a2RmSjU4M1NWVWluNHViOXRhMll4cU9MTm1iNnhRMkJmWVB4b0luOXB0YTA2bFcxUTNuNDFUOElSCndya1A5QllYZXlVZlRXeTgxazFXdFRYUmV0VnZ1S3JaeDZFdy9oWTNwcjdvTzFnRFlzTVgzVDQ2bFRQS0Z0aVkKOWMzcHphc3JyT01Bd1dDTDFaakxCUHYra1JRT09JTT0KLS0tLS1FTkQgUFJJVkFURSBLRVktLS0tLQo=

...


root@jumpbox:~/kubernetes-the-hard-way# ls -l *.kubeconfig
-rw------- 1 root root  9953 Jan 11 07:53 admin.kubeconfig
-rw------- 1 root root 10305 Jan 11 07:53 kube-controller-manager.kubeconfig
-rw------- 1 root root 10187 Jan 11 07:52 kube-proxy.kubeconfig
-rw------- 1 root root 10211 Jan 11 07:53 kube-scheduler.kubeconfig
-rw------- 1 root root 10161 Jan 11 07:49 node-0.kubeconfig
-rw------- 1 root root 10161 Jan 11 07:49 node-1.kubeconfig

# kubelet, kube-proxy kubeconfig 파일을 node-0, node-1에 복사
root@jumpbox:~/kubernetes-the-hard-way# for host in node-0 node-1; do
  ssh root@${host} "mkdir -p /var/lib/{kube-proxy,kubelet}"

  scp kube-proxy.kubeconfig \
    root@${host}:/var/lib/kube-proxy/kubeconfig \

  scp ${host}.kubeconfig \
    root@${host}:/var/lib/kubelet/kubeconfig
done
kube-proxy.kubeconfig                                                                                                                                        100%   10KB   8.8MB/s   00:00
node-0.kubeconfig                                                                                                                                            100%   10KB  12.1MB/s   00:00
kube-proxy.kubeconfig                                                                                                                                        100%   10KB  12.0MB/s   00:00
node-1.kubeconfig                                                                                                                                            100%   10KB  10.5MB/s   00:00

root@jumpbox:~/kubernetes-the-hard-way# ssh node-0 ls -l /var/lib/*/kubeconfig
-rw------- 1 root root 10161 Jan 11 07:55 /var/lib/kubelet/kubeconfig
-rw------- 1 root root 10187 Jan 11 07:55 /var/lib/kube-proxy/kubeconfig
root@jumpbox:~/kubernetes-the-hard-way# ssh node-1 ls -l /var/lib/*/kubeconfig
-rw------- 1 root root 10161 Jan 11 07:55 /var/lib/kubelet/kubeconfig
-rw------- 1 root root 10187 Jan 11 07:55 /var/lib/kube-proxy/kubeconfig

# kube-controller-manager,kube-scheduler kubeconfig files을 서버로 복사
root@jumpbox:~/kubernetes-the-hard-way# scp admin.kubeconfig \
  kube-controller-manager.kubeconfig \
  kube-scheduler.kubeconfig \
  root@server:~/
admin.kubeconfig                                                                                                                                             100% 9953     9.7MB/s   00:00
kube-controller-manager.kubeconfig                                                                                                                           100%   10KB  12.8MB/s   00:00
kube-scheduler.kubeconfig                                                                                                                                    100%   10KB  14.4MB/s   00:00

root@jumpbox:~/kubernetes-the-hard-way# ssh server ls -l /root/*.kubeconfig
-rw------- 1 root root  9953 Jan 11 07:56 /root/admin.kubeconfig
-rw------- 1 root root 10305 Jan 11 07:56 /root/kube-controller-manager.kubeconfig
-rw------- 1 root root 10211 Jan 11 07:56 /root/kube-scheduler.kubeconfig

 

 

데이터 암호화를 위한 설정 및 키 생성

이 단계는 Kubernetes API Server가 Secret을 etcd에 저장할 때 평문이 아닌 암호화된 형태로 저장하도록 설정하는 과정입니다. 

# 암호키 생성
root@jumpbox:~/kubernetes-the-hard-way# export ENCRYPTION_KEY=$(head -c 32 /dev/urandom | base64)
echo $ENCRYPTION_KEY
pR499HLO7RNc0VAgKmO9WqlfgE/rqBRsGskyllCp3Xo=


# Create the encryption-config.yaml encryption config file
# (참고) 실제 etcd 값에 기록되는 헤더 : k8s:enc:aescbc:v1:key1:<ciphertext>
root@jumpbox:~/kubernetes-the-hard-way# cat configs/encryption-config.yaml
kind: EncryptionConfiguration  # kube-apiserver가 etcd에 저장할 리소스를 어떻게 암호화할지 정의
apiVersion: apiserver.config.k8s.io/v1  # --encryption-provider-config 플래그로 참조
resources:
  - resources:
      - secrets  # 암호화 대상 Kubernetes 리소스 : 여기서는 Secret 리소스만 암호화
    providers:  # 지원 providers(위 부터 적용됨) : identity, aescbc, aesgcm, kms v2, secretbox
      - aescbc:  # etcd에 저장될 Secret을 AES-CBC 방식으로 암호화
          keys:
            - name: key1  # 키 식별자 (etcd 데이터에 기록됨)
              secret: ${ENCRYPTION_KEY}
      - identity: {}  # 암호화하지 않음 (Plaintext), 주로 하위 호환성 / 점진적 암호화 목적
      
      
root@jumpbox:~/kubernetes-the-hard-way# cat configs/encryption-config.yaml
kind: EncryptionConfiguration
apiVersion: apiserver.config.k8s.io/v1
resources:
  - resources:
      - secrets
    providers:
      - aescbc:
          keys:
            - name: key1
              secret: ${ENCRYPTION_KEY}
      - identity: {}
root@jumpbox:~/kubernetes-the-hard-way#
root@jumpbox:~/kubernetes-the-hard-way#
root@jumpbox:~/kubernetes-the-hard-way# envsubst < configs/encryption-config.yaml > encryption-config.yaml
root@jumpbox:~/kubernetes-the-hard-way# cat encryption-config.yaml
kind: EncryptionConfiguration
apiVersion: apiserver.config.k8s.io/v1
resources:
  - resources:
      - secrets
    providers:
      - aescbc:
          keys:
            - name: key1
              secret: pR499HLO7RNc0VAgKmO9WqlfgE/rqBRsGskyllCp3Xo=
      - identity: {}
      
# encryption-config.yaml, encryption config file을 controller instance에 복사
root@jumpbox:~/kubernetes-the-hard-way# scp encryption-config.yaml root@server:~/
encryption-config.yaml                                                                                                                                     100%  271   343.0KB/s   00:00
root@jumpbox:~/kubernetes-the-hard-way# ssh server ls -l /root/encryption-config.yaml
-rw-r--r-- 1 root root 271 Jan 11 08:04 /root/encryption-config.yaml

 

etcd 클러스터 부트스트래핑

server 노드에 etcd 서비스 기동하겠습니다.

# Prerequisites

# hostname 변경 : controller -> server
# http 평문 통신!
# 각 etcd 멤버는 etcd 클러스터에서 모두 고유한 이름을 가져야합니다. 
# etcd 이름을 현재의 compute instance에 맞추어 지정합니다.

root@jumpbox:~/kubernetes-the-hard-way# cat units/etcd.service | grep controller
  --name controller \
  --initial-cluster controller=http://127.0.0.1:2380 \

root@jumpbox:~/kubernetes-the-hard-way# ETCD_NAME=server
root@jumpbox:~/kubernetes-the-hard-way# cat > units/etcd.service <<EOF
[Unit]
Description=etcd
Documentation=https://github.com/etcd-io/etcd

[Service]
Type=notify
ExecStart=/usr/local/bin/etcd \\
  --name ${ETCD_NAME} \\
  --initial-advertise-peer-urls http://127.0.0.1:2380 \\
  --listen-peer-urls http://127.0.0.1:2380 \\
  --listen-client-urls http://127.0.0.1:2379 \\
  --advertise-client-urls http://127.0.0.1:2379 \\
  --initial-cluster-token etcd-cluster-0 \\
  --initial-cluster ${ETCD_NAME}=http://127.0.0.1:2380 \\
  --initial-cluster-state new \\
  --data-dir=/var/lib/etcd
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF


root@jumpbox:~/kubernetes-the-hard-way# cat units/etcd.service | grep server
  --name server \
  --initial-cluster server=http://127.0.0.1:2380 \


# etcd 바이너리 파일과 systemd 유닛 파일을 서버에 복사합니다. 
root@jumpbox:~/kubernetes-the-hard-way# scp \
  downloads/controller/etcd \
  downloads/client/etcdctl \
  units/etcd.service \
  root@server:~/
etcd                                                                                                                                                       100%   23MB  96.5MB/s   00:00
etcdctl                                                                                                                                                    100%   15MB 135.0MB/s   00:00
etcd.service                                                                                                                                               100%  564     1.2MB/s   00:00


# 아래는 server 가상머신 접속 후 명령 실행

root@jumpbox:~/kubernetes-the-hard-way# ssh root@server

# Bootstrapping an etcd Cluster
# etcd 바이너리 파일 설치
root@server:~# pwd
/root
root@server:~# mv etcd etcdctl /usr/local/bin/

# etcd 서버 설정
root@server:~# mkdir -p /etc/etcd /var/lib/etcd
root@server:~# chmod 700 /var/lib/etcd
root@server:~# cp ca.crt kube-api-server.key kube-api-server.crt /etc/etcd/

# etcd.service, systemd 유닛 파일 생성
root@server:~# mv etcd.service /etc/systemd/system/
root@server:~# tree /etc/systemd/system/
/etc/systemd/system/
├── apt-daily.service -> /dev/null
├── apt-daily-upgrade.service -> /dev/null
├── dbus-org.freedesktop.timesync1.service -> /lib/systemd/system/systemd-timesyncd.service
├── etcd.service
├── getty.target.wants
│   └── getty@tty1.service -> /lib/systemd/system/getty@.service
├── multi-user.target.wants
│   ├── console-setup.service -> /lib/systemd/system/console-setup.service
│   ├── cron.service -> /lib/systemd/system/cron.service
│   ├── e2scrub_reap.service -> /lib/systemd/system/e2scrub_reap.service
│   ├── networking.service -> /lib/systemd/system/networking.service
│   ├── nfs-client.target -> /lib/systemd/system/nfs-client.target
│   ├── remote-fs.target -> /lib/systemd/system/remote-fs.target
│   ├── rpcbind.service -> /lib/systemd/system/rpcbind.service
│   ├── ssh.service -> /lib/systemd/system/ssh.service
│   ├── vboxadd.service -> /lib/systemd/system/vboxadd.service
│   └── vboxadd-service.service -> /lib/systemd/system/vboxadd-service.service
├── network-online.target.wants
│   └── networking.service -> /lib/systemd/system/networking.service
├── paths.target.wants
│   └── acpid.path -> /lib/systemd/system/acpid.path
├── remote-fs.target.wants
│   └── nfs-client.target -> /lib/systemd/system/nfs-client.target
├── sockets.target.wants
│   ├── acpid.socket -> /lib/systemd/system/acpid.socket
│   ├── dm-event.socket -> /lib/systemd/system/dm-event.socket
│   └── rpcbind.socket -> /lib/systemd/system/rpcbind.socket
├── sshd.service -> /lib/systemd/system/ssh.service
├── sysinit.target.wants
│   ├── blk-availability.service -> /lib/systemd/system/blk-availability.service
│   ├── keyboard-setup.service -> /lib/systemd/system/keyboard-setup.service
│   ├── lvm2-lvmpolld.socket -> /lib/systemd/system/lvm2-lvmpolld.socket
│   ├── lvm2-monitor.service -> /lib/systemd/system/lvm2-monitor.service
│   ├── systemd-pstore.service -> /lib/systemd/system/systemd-pstore.service
│   └── systemd-timesyncd.service -> /lib/systemd/system/systemd-timesyncd.service
└── timers.target.wants
    ├── dpkg-db-backup.timer -> /lib/systemd/system/dpkg-db-backup.timer
    ├── e2scrub_all.timer -> /lib/systemd/system/e2scrub_all.timer
    ├── fstrim.timer -> /lib/systemd/system/fstrim.timer
    ├── logrotate.timer -> /lib/systemd/system/logrotate.timer
    └── man-db.timer -> /lib/systemd/system/man-db.timer

9 directories, 33 files

# etcd 서버 시작
root@server:~# systemctl daemon-reload
root@server:~# systemctl enable etcd
Created symlink /etc/systemd/system/multi-user.target.wants/etcd.service → /etc/systemd/system/etcd.service.
root@server:~# systemctl start etcd

root@server:~# systemctl status etcd --no-pager
● etcd.service - etcd
     Loaded: loaded (/etc/systemd/system/etcd.service; enabled; preset: enabled)
     Active: active (running) since Sun 2026-01-11 08:19:06 KST; 2min 11s ago
       Docs: https://github.com/etcd-io/etcd
   Main PID: 2627 (etcd)
      Tasks: 7 (limit: 2096)
     Memory: 9.2M
        CPU: 1.148s
     CGroup: /system.slice/etcd.service
             └─2627 /usr/local/bin/etcd --name server --initial-advertise-peer-urls http://127.0.0.1:2380 --listen-peer-urls http://127.0.0.1:2380 --listen-client-urls http://127.0.0.1:237…

Jan 11 08:19:06 server etcd[2627]: {"level":"info","ts":"2026-01-11T08:19:06.399737+0900","caller":"membership/cluster.go:647","msg":"set initial cluster version","cluster-i…version":"3.6"}
Jan 11 08:19:06 server etcd[2627]: {"level":"info","ts":"2026-01-11T08:19:06.399834+0900","caller":"api/capability.go:76","msg":"enabled capabilities for version","cluster-version":"3.6"}
Jan 11 08:19:06 server etcd[2627]: {"level":"info","ts":"2026-01-11T08:19:06.399881+0900","caller":"etcdserver/server.go:2383","msg":"cluster version is updated","cluster-version":"3.6"}
Jan 11 08:19:06 server etcd[2627]: {"level":"info","ts":"2026-01-11T08:19:06.400006+0900","caller":"etcdmain/main.go:44","msg":"notifying init daemon"}
Jan 11 08:19:06 server etcd[2627]: {"level":"info","ts":"2026-01-11T08:19:06.400040+0900","caller":"version/monitor.go:116","msg":"cluster version differs from storage versi…rsion":"3.5.0"}
Jan 11 08:19:06 server etcd[2627]: {"level":"info","ts":"2026-01-11T08:19:06.400109+0900","caller":"schema/migration.go:65","msg":"updated storage version","new-storage-version":"3.6.0"}
Jan 11 08:19:06 server etcd[2627]: {"level":"info","ts":"2026-01-11T08:19:06.402219+0900","caller":"v3rpc/health.go:63","msg":"grpc service status changed","service":"","status":"SERVING"}
Jan 11 08:19:06 server etcd[2627]: {"level":"info","ts":"2026-01-11T08:19:06.404687+0900","caller":"etcdmain/main.go:50","msg":"successfully notified init daemon"}
Jan 11 08:19:06 server systemd[1]: Started etcd.service - etcd.
Jan 11 08:19:06 server etcd[2627]: {"level":"info","ts":"2026-01-11T08:19:06.407277+0900","caller":"embed/serve.go:220","msg":"serving client traffic insecurely; this is str…27.0.0.1:2379"}
Hint: Some lines were ellipsized, use -l to show in full.

root@server:~# ss -tnlp | grep etcd
LISTEN 0      4096       127.0.0.1:2379      0.0.0.0:*    users:(("etcd",pid=2627,fd=6))
LISTEN 0      4096       127.0.0.1:2380      0.0.0.0:*    users:(("etcd",pid=2627,fd=3))

root@server:~# etcdctl member list
6702b0a34e2cfd39, started, server, http://127.0.0.1:2380, http://127.0.0.1:2379, false

root@server:~# etcdctl member list -w table
+------------------+---------+--------+-----------------------+-----------------------+------------+
|        ID        | STATUS  |  NAME  |      PEER ADDRS       |     CLIENT ADDRS      | IS LEARNER |
+------------------+---------+--------+-----------------------+-----------------------+------------+
| 6702b0a34e2cfd39 | started | server | http://127.0.0.1:2380 | http://127.0.0.1:2379 |      false |
+------------------+---------+--------+-----------------------+-----------------------+------------+

root@server:~# etcdctl endpoint status -w table
+----------------+------------------+------------+-----------------+---------+--------+-----------------------+-------+-----------+------------+-----------+------------+--------------------+--------+--------------------------+-------------------+
|    ENDPOINT    |        ID        |  VERSION   | STORAGE VERSION | DB SIZE | IN USE | PERCENTAGE NOT IN USE | QUOTA | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS | DOWNGRADE TARGET VERSION | DOWNGRADE ENABLED |
+----------------+------------------+------------+-----------------+---------+--------+-----------------------+-------+-----------+------------+-----------+------------+--------------------+--------+--------------------------+-------------------+
| 127.0.0.1:2379 | 6702b0a34e2cfd39 | 3.6.0-rc.3 |           3.6.0 |   20 kB |  16 kB |                   20% |   0 B |      true |      false |         2 |          4 |                  4 |        |                          |             false |
+----------------+------------------+------------+-----------------+---------+--------+-----------------------+-------+-----------+------------+-----------+------------+--------------------+--------+--------------------------+-------------------+

 

 

컨트롤 플레인 부트스트래핑

server 노드에 api server, scheduler, kube controller manager 서비스 기동하겠습니다.

# api -> kubelet 호출 시 Flow
kube-apiserver (client)
  |
  | (TLS client cert, CN=kubernetes)
  ↓
kubelet API Server 역할 (/stats, /log, /metrics)
  |
  ↓
RBAC 평가:
  User = kubernetes
  → ClusterRoleBinding system:kube-apiserver 매칭
  → ClusterRole system:kube-apiserver-to-kubelet 권한 부여

 

 

# kube-apiserver.service 수정 : service-cluster-ip-range 추가
# https://github.com/kelseyhightower/kubernetes-the-hard-way/issues/905
# service-cluster-ip 값은 ca.conf 에 설정한 [kube-api-server_alt_names] 항목의 Service IP 범위
root@jumpbox:~/kubernetes-the-hard-way# cat ca.conf | grep '\[kube-api-server_alt_names' -A2
[kube-api-server_alt_names]
IP.0  = 127.0.0.1
IP.1  = 10.32.0.1


root@jumpbox:~/kubernetes-the-hard-way# cat << EOF > units/kube-apiserver.service
[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/kubernetes/kubernetes

[Service]
ExecStart=/usr/local/bin/kube-apiserver \\
  --allow-privileged=true \\
  --apiserver-count=1 \\
  --audit-log-maxage=30 \\
  --audit-log-maxbackup=3 \\
  --audit-log-maxsize=100 \\
  --audit-log-path=/var/log/audit.log \\
  --authorization-mode=Node,RBAC \\
  --bind-address=0.0.0.0 \\
  --client-ca-file=/var/lib/kubernetes/ca.crt \\
  --enable-admission-plugins=NamespaceLifecycle,NodeRestriction,LimitRanger,ServiceAccount,DefaultStorageClass,ResourceQuota \\
  --etcd-servers=http://127.0.0.1:2379 \\
  --event-ttl=1h \\
  --encryption-provider-config=/var/lib/kubernetes/encryption-config.yaml \\
  --kubelet-certificate-authority=/var/lib/kubernetes/ca.crt \\
  --kubelet-client-certificate=/var/lib/kubernetes/kube-api-server.crt \\
  --kubelet-client-key=/var/lib/kubernetes/kube-api-server.key \\
  --runtime-config='api/all=true' \\
  --service-account-key-file=/var/lib/kubernetes/service-accounts.crt \\
  --service-account-signing-key-file=/var/lib/kubernetes/service-accounts.key \\
  --service-account-issuer=https://server.kubernetes.local:6443 \\
  --service-cluster-ip-range=10.32.0.0/24 \\
  --service-node-port-range=30000-32767 \\
  --tls-cert-file=/var/lib/kubernetes/kube-api-server.crt \\
  --tls-private-key-file=/var/lib/kubernetes/kube-api-server.key \\
  --v=2
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

# kube-apiserver가 kubelet(Node)에 접근할 수 있도록 허용하는 '시스템 내부용 RBAC' 설정
root@jumpbox:~/kubernetes-the-hard-way# cat configs/kube-apiserver-to-kubelet.yaml ; echo
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"  # Kubernetes가 업그레이드 시 자동 관리
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
  name: system:kube-apiserver-to-kubelet
rules:
  - apiGroups:
      - ""
    resources:
      - nodes/proxy
      - nodes/stats
      - nodes/log
      - nodes/spec
      - nodes/metrics
    verbs:
      - "*"
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: system:kube-apiserver  # 누가 이 권한을 쓰는가? → kube-apiserver 자신
  namespace: ""
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:kube-apiserver-to-kubelet
subjects:
  - apiGroup: rbac.authorization.k8s.io
    kind: User
    name: kubernetes  # 사용자 kubernetes ,이 사용자는 kube-apiserver가 사용하는 클라이언트 인증서의 CN
    

# api-server : Subject CN 확인
root@jumpbox:~/kubernetes-the-hard-way# openssl x509 -in kube-api-server.crt -text -noout
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            2b:03:f7:ba:63:e9:26:c8:a5:c1:9f:dd:8b:d8:df:4c:aa:56:f5:75
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C = US, ST = Washington, L = Seattle, CN = CA
        Validity
            Not Before: Jan 10 22:28:57 2026 GMT
            Not After : Jan 11 22:28:57 2036 GMT
        Subject: CN = kubernetes, C = US, ST = Washington, L = Seattle
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (4096 bit)
                Modulus:
                    00:96:43:8b:18:ed:f0:ab:92:9b:3d:21:22:28:f7:
                    13:48:d0:5e:26:0e:f9:e8:09:ce:29:8b:e4:f5:2a:
                    7b:bd:33:37:8d:a7:a5:42:28:2c:c0:ee:35:db:11:
                    0a:84:da:d3:ef:c1:7f:fa:bb:66:81:bf:d9:8a:fb:
                    74:c7:ed:20:e6:81:f8:5c:2a:98:18:c7:10:61:6d:
                    e8:0d:44:6b:7a:2c:c4:ad:e0:21:b9:d2:dd:dc:53:
                    56:8c:1c:03:e6:40:bc:e1:7b:32:b5:7b:2b:e6:85:
                    4d:6b:e2:db:20:e6:7b:ac:18:bf:69:ae:ca:0e:1b:
                    45:14:0c:0a:5d:c1:c6:30:7c:5e:d4:87:45:4a:97:
                    54:16:7e:b6:99:16:36:98:30:cd:60:4b:cb:0d:9f:
                    95:30:c5:f6:7c:0e:9d:6f:e2:ea:b1:a1:3a:aa:c6:
                    0e:e8:35:75:55:e3:a1:ef:6b:fd:0f:2e:a1:1b:14:
                    d5:e6:e5:16:67:a0:65:3c:a7:9b:b6:34:44:f6:60:
                    27:64:39:0a:c2:ca:51:db:89:44:6a:6c:cc:47:ec:
                    73:72:05:9d:b2:82:76:4d:60:e3:3a:e8:cf:d4:61:
                    6b:aa:ab:6c:2d:85:13:36:fb:01:04:b7:57:7c:91:
                    5d:08:4f:61:5c:d3:a3:62:8f:1a:2f:51:24:a1:9a:
                    a9:5a:8d:0c:04:e2:e4:16:ad:46:af:99:45:32:a5:
                    aa:a7:b7:6a:37:9b:60:aa:76:24:5f:48:40:76:b1:
                    09:0f:b0:85:04:eb:d5:0d:2e:86:d2:4a:e5:10:e7:
                    36:28:e8:d8:41:ba:e5:5d:98:e2:72:97:cf:6d:89:
                    4b:59:1a:44:f9:72:1d:f8:e9:03:01:3b:ac:61:b6:
                    b0:95:c0:c2:7a:b4:e4:da:7a:54:be:a6:7c:1a:4f:
                    57:66:b3:26:67:0d:7b:f2:60:ce:99:c5:79:3b:86:
                    79:dd:50:67:c3:4a:85:fb:e4:47:61:c8:7f:07:c4:
                    98:1f:d0:f4:e5:53:c4:ad:d9:e9:ab:4c:14:6b:3c:
                    50:c9:5c:6b:d5:7c:cd:bd:c4:a2:2e:e5:57:61:3e:
                    7f:b5:a2:59:42:c8:46:64:31:82:a3:d4:46:55:35:
                    db:cc:4b:ce:54:47:83:d7:7e:56:ec:76:8c:7c:67:
                    00:02:9d:b4:d1:fc:e0:60:a3:c7:9b:6a:28:3e:cf:
                    0b:e4:50:f8:78:32:ac:75:8c:ba:8e:8d:8a:1a:62:
                    ed:1a:74:c6:71:1a:c1:4c:ec:f6:0a:c5:0d:ae:1a:
                    c9:d6:f7:6e:a0:9c:97:48:93:f6:2c:f8:77:6d:8c:
                    50:5a:fd:3d:38:80:c0:fe:81:55:c3:ce:27:e2:07:
                    fa:52:9f
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:FALSE
            X509v3 Extended Key Usage:
                TLS Web Client Authentication, TLS Web Server Authentication
            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment
            Netscape Cert Type:
                SSL Client, SSL Server
            Netscape Comment:
                Kube API Server Certificate
            X509v3 Subject Alternative Name:
                IP Address:127.0.0.1, IP Address:10.32.0.1, DNS:kubernetes, DNS:kubernetes.default, DNS:kubernetes.default.svc, DNS:kubernetes.default.svc.cluster, DNS:kubernetes.svc.cluster.local, DNS:server.kubernetes.local, DNS:api-server.kubernetes.local
            X509v3 Subject Key Identifier:
                CA:7C:90:05:B6:3F:7B:38:75:8B:AA:2C:09:B9:17:94:60:F2:2F:0F
            X509v3 Authority Key Identifier:
                9E:CD:36:BA:22:6B:43:A7:DB:23:29:97:53:1B:D1:72:DF:6D:61:D2
    Signature Algorithm: sha256WithRSAEncryption
    Signature Value:
        21:c5:6b:cd:66:86:8b:34:99:a3:ab:04:2a:ba:d4:3b:25:86:
        11:ab:f5:97:57:55:4c:c2:b3:57:f2:5f:06:a7:07:b6:10:ef:
        60:8f:eb:af:48:f5:f7:c0:80:fd:50:7d:98:b6:82:a3:6b:44:
        05:4c:06:59:ec:6e:33:be:0f:58:de:bd:94:d1:54:b9:7d:53:
        09:b3:ca:32:e8:c9:64:e3:f4:1a:ab:bd:94:3b:38:fd:10:49:
        8f:fa:17:aa:25:06:b2:78:48:26:7a:1d:e0:1a:73:4f:61:63:
        92:01:e9:37:84:9e:dd:e5:23:ba:7d:8d:9d:c0:83:75:16:95:
        f4:29:95:aa:f2:27:d4:c1:3a:57:d9:65:66:1a:f2:dd:27:5e:
        d0:6c:47:3e:a7:75:06:7c:96:aa:5e:39:3b:e1:d9:be:0b:a7:
        3a:71:a9:0b:49:4a:d0:ca:41:a2:52:0c:d1:a6:62:20:45:d6:
        b3:29:bc:b9:8c:04:d5:b9:41:af:7a:42:5f:2c:00:cf:80:a4:
        54:a4:a0:e2:fa:52:8d:da:57:ac:76:af:1f:ee:3a:d2:0c:2a:
        9a:bb:ea:a2:bf:10:30:ab:f3:20:b4:e6:cc:c9:81:2b:63:c5:
        8d:90:6d:71:84:10:cb:b0:3b:e0:c5:36:61:0a:fe:8b:f5:c1:
        ed:28:ca:e4:c5:8d:8e:9d:9b:86:d4:81:de:26:a0:fd:e4:d1:
        a1:1c:48:e5:83:4e:d7:a8:bd:6f:d6:f7:19:56:a9:34:3e:ff:
        a7:a8:4c:96:c9:b3:a6:eb:2c:ae:a2:b6:58:b3:0a:7d:0b:4d:
        3f:31:a9:25:41:1c:cd:7c:e0:f2:7e:aa:47:a4:2a:6f:9b:30:
        2a:6e:46:cd:50:05:04:69:89:17:66:cd:7b:4b:01:1a:12:50:
        53:2b:e5:f9:34:49:a3:a3:e0:5a:61:11:34:aa:fa:2d:3b:f3:
        22:b6:3c:32:4a:90:ab:3c:f9:01:2f:43:5a:78:80:93:5e:66:
        4d:ad:7b:a2:09:34:17:3b:ce:0b:94:14:f8:5a:01:ab:98:a7:
        ba:4c:0f:70:ff:3b:3c:01:0f:97:9a:6b:5b:76:9e:8b:b5:10:
        49:3d:ae:6a:40:c8:16:80:af:c4:61:b3:28:f7:32:21:bf:7a:
        36:6f:97:f2:ae:b2:06:6c:75:5e:99:47:f2:a6:6b:09:3b:e3:
        b7:cd:29:3c:89:62:29:d7:83:78:13:4b:29:be:41:58:e9:8e:
        a1:a5:07:c2:12:02:ea:85:5c:6d:13:8f:d5:49:a7:25:83:09:
        ca:fc:04:81:0e:d6:5a:03:db:55:e1:0b:c2:de:13:ca:c1:ae:
        36:e9:cc:a3:3e:80:ee:67
        
        
root@jumpbox:~/kubernetes-the-hard-way# cat units/kube-scheduler.service ; echo
[Unit]
Description=Kubernetes Scheduler
Documentation=https://github.com/kubernetes/kubernetes

[Service]
ExecStart=/usr/local/bin/kube-scheduler \
  --config=/etc/kubernetes/config/kube-scheduler.yaml \
  --v=2
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

root@jumpbox:~/kubernetes-the-hard-way# cat configs/kube-scheduler.yaml ; echo
apiVersion: kubescheduler.config.k8s.io/v1
kind: KubeSchedulerConfiguration
clientConnection:
  kubeconfig: "/var/lib/kubernetes/kube-scheduler.kubeconfig"
leaderElection:
  leaderElect: true
  
root@jumpbox:~/kubernetes-the-hard-way# cat units/kube-controller-manager.service ; echo
[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/kubernetes/kubernetes

[Service]
ExecStart=/usr/local/bin/kube-controller-manager \
  --bind-address=0.0.0.0 \
  --cluster-cidr=10.200.0.0/16 \
  --cluster-name=kubernetes \
  --cluster-signing-cert-file=/var/lib/kubernetes/ca.crt \
  --cluster-signing-key-file=/var/lib/kubernetes/ca.key \
  --kubeconfig=/var/lib/kubernetes/kube-controller-manager.kubeconfig \
  --root-ca-file=/var/lib/kubernetes/ca.crt \
  --service-account-private-key-file=/var/lib/kubernetes/service-accounts.key \
  --service-cluster-ip-range=10.32.0.0/24 \
  --use-service-account-credentials=true \
  --v=2
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target


# jumpbox에 연결하고 쿠버네티스 바이너리 파일과 systemd 유닛 파일을 복사합니다.
root@jumpbox:~/kubernetes-the-hard-way# scp \
  downloads/controller/kube-apiserver \
  downloads/controller/kube-controller-manager \
  downloads/controller/kube-scheduler \
  downloads/client/kubectl \
  units/kube-apiserver.service \
  units/kube-controller-manager.service \
  units/kube-scheduler.service \
  configs/kube-scheduler.yaml \
  configs/kube-apiserver-to-kubelet.yaml \
  root@server:~/
kube-apiserver                                                                                                                                               100%   86MB 120.2MB/s   00:00
kube-controller-manager                                                                                                                                      100%   80MB 107.7MB/s   00:00
kube-scheduler                                                                                                                                               100%   61MB  84.2MB/s   00:00
kubectl                                                                                                                                                      100%   53MB  61.5MB/s   00:00
kube-apiserver.service                                                                                                                                       100% 1442     1.4MB/s   00:00
kube-controller-manager.service                                                                                                                              100%  735     1.0MB/s   00:00
kube-scheduler.service                                                                                                                                       100%  281   408.4KB/s   00:00
kube-scheduler.yaml                                                                                                                                          100%  191   288.9KB/s   00:00
kube-apiserver-to-kubelet.yaml                                                                                                                               100%  727     1.0MB/s   00:00

# 확인
root@jumpbox:~/kubernetes-the-hard-way# ssh server ls -l /root
total 286964
-rw------- 1 root root     9953 Jan 11 07:56 admin.kubeconfig
-rw-r--r-- 1 root root     1899 Jan 11 07:36 ca.crt
-rw------- 1 root root     3272 Jan 11 07:36 ca.key
-rw-r--r-- 1 root root      271 Jan 11 08:04 encryption-config.yaml
-rwxr-xr-x 1 root root 90243224 Jan 11 08:28 kube-apiserver
-rw-r--r-- 1 root root     2354 Jan 11 07:36 kube-api-server.crt
-rw------- 1 root root     3268 Jan 11 07:36 kube-api-server.key
-rw-r--r-- 1 root root     1442 Jan 11 08:28 kube-apiserver.service
-rw-r--r-- 1 root root      727 Jan 11 08:28 kube-apiserver-to-kubelet.yaml
-rwxr-xr-x 1 root root 83427480 Jan 11 08:28 kube-controller-manager
-rw------- 1 root root    10305 Jan 11 07:56 kube-controller-manager.kubeconfig
-rw-r--r-- 1 root root      735 Jan 11 08:28 kube-controller-manager.service
-rwxr-xr-x 1 root root 55836824 Jan 11 08:28 kubectl
-rwxr-xr-x 1 root root 64225432 Jan 11 08:28 kube-scheduler
-rw------- 1 root root    10211 Jan 11 07:56 kube-scheduler.kubeconfig
-rw-r--r-- 1 root root      281 Jan 11 08:28 kube-scheduler.service
-rw-r--r-- 1 root root      191 Jan 11 08:28 kube-scheduler.yaml
-rw-r--r-- 1 root root     2004 Jan 11 07:36 service-accounts.crt
-rw------- 1 root root     3272 Jan 11 07:36 service-accounts.key

 

쿠버네티스 컨트롤 플레인 프로비저닝을 진행하겠습니다.

 

root@jumpbox:~/kubernetes-the-hard-way# ssh root@server

# 서버 접근
root@server:~# pwd
/root
root@server:~# mkdir -p /etc/kubernetes/config

# 쿠버네티스 바이너리 설치
root@server:~# mv kube-apiserver \
  kube-controller-manager \
  kube-scheduler kubectl \
  /usr/local/bin/
root@server:~# ls -l /usr/local/bin/kube-*
-rwxr-xr-x 1 root root 90243224 Jan 11 08:28 /usr/local/bin/kube-apiserver
-rwxr-xr-x 1 root root 83427480 Jan 11 08:28 /usr/local/bin/kube-controller-manager
-rwxr-xr-x 1 root root 64225432 Jan 11 08:28 /usr/local/bin/kube-scheduler

# 쿠버네티스 api server 설정
root@server:~# mkdir -p /var/lib/kubernetes/
root@server:~# mv ca.crt ca.key \
  kube-api-server.key kube-api-server.crt \
  service-accounts.key service-accounts.crt \
  encryption-config.yaml \
  /var/lib/kubernetes/
root@server:~# ls -l /var/lib/kubernetes/
total 28
-rw-r--r-- 1 root root 1899 Jan 11 07:36 ca.crt
-rw------- 1 root root 3272 Jan 11 07:36 ca.key
-rw-r--r-- 1 root root  271 Jan 11 08:04 encryption-config.yaml
-rw-r--r-- 1 root root 2354 Jan 11 07:36 kube-api-server.crt
-rw------- 1 root root 3268 Jan 11 07:36 kube-api-server.key
-rw-r--r-- 1 root root 2004 Jan 11 07:36 service-accounts.crt
-rw------- 1 root root 3272 Jan 11 07:36 service-accounts.key

# kube-apiserver.service systemd 유닛 파일 생서
root@server:~# mv kube-apiserver.service \
  /etc/systemd/system/kube-apiserver.service
root@server:~# tree /etc/systemd/system
/etc/systemd/system
├── apt-daily.service -> /dev/null
├── apt-daily-upgrade.service -> /dev/null
├── dbus-org.freedesktop.timesync1.service -> /lib/systemd/system/systemd-timesyncd.service
├── etcd.service
├── getty.target.wants
│   └── getty@tty1.service -> /lib/systemd/system/getty@.service
├── kube-apiserver.service
├── multi-user.target.wants
│   ├── console-setup.service -> /lib/systemd/system/console-setup.service
│   ├── cron.service -> /lib/systemd/system/cron.service
│   ├── e2scrub_reap.service -> /lib/systemd/system/e2scrub_reap.service
│   ├── etcd.service -> /etc/systemd/system/etcd.service
│   ├── networking.service -> /lib/systemd/system/networking.service
│   ├── nfs-client.target -> /lib/systemd/system/nfs-client.target
│   ├── remote-fs.target -> /lib/systemd/system/remote-fs.target
│   ├── rpcbind.service -> /lib/systemd/system/rpcbind.service
│   ├── ssh.service -> /lib/systemd/system/ssh.service
│   ├── vboxadd.service -> /lib/systemd/system/vboxadd.service
│   └── vboxadd-service.service -> /lib/systemd/system/vboxadd-service.service
├── network-online.target.wants
│   └── networking.service -> /lib/systemd/system/networking.service
├── paths.target.wants
│   └── acpid.path -> /lib/systemd/system/acpid.path
├── remote-fs.target.wants
│   └── nfs-client.target -> /lib/systemd/system/nfs-client.target
├── sockets.target.wants
│   ├── acpid.socket -> /lib/systemd/system/acpid.socket
│   ├── dm-event.socket -> /lib/systemd/system/dm-event.socket
│   └── rpcbind.socket -> /lib/systemd/system/rpcbind.socket
├── sshd.service -> /lib/systemd/system/ssh.service
├── sysinit.target.wants
│   ├── blk-availability.service -> /lib/systemd/system/blk-availability.service
│   ├── keyboard-setup.service -> /lib/systemd/system/keyboard-setup.service
│   ├── lvm2-lvmpolld.socket -> /lib/systemd/system/lvm2-lvmpolld.socket
│   ├── lvm2-monitor.service -> /lib/systemd/system/lvm2-monitor.service
│   ├── systemd-pstore.service -> /lib/systemd/system/systemd-pstore.service
│   └── systemd-timesyncd.service -> /lib/systemd/system/systemd-timesyncd.service
└── timers.target.wants
    ├── dpkg-db-backup.timer -> /lib/systemd/system/dpkg-db-backup.timer
    ├── e2scrub_all.timer -> /lib/systemd/system/e2scrub_all.timer
    ├── fstrim.timer -> /lib/systemd/system/fstrim.timer
    ├── logrotate.timer -> /lib/systemd/system/logrotate.timer
    └── man-db.timer -> /lib/systemd/system/man-db.timer

9 directories, 35 files


# 쿠버네티스 컨트롤러 매니저 구성
root@server:~# mv kube-controller-manager.kubeconfig /var/lib/kubernetes/
root@server:~# mv kube-controller-manager.service /etc/systemd/system/
root@server:~# mv kube-scheduler.kubeconfig /var/lib/kubernetes/
root@server:~# mv kube-scheduler.yaml /etc/kubernetes/config/
root@server:~# mv kube-scheduler.service /etc/systemd/system/

# 컨트롤러 서비스 시작
root@server:~# systemctl daemon-reload
root@server:~# systemctl enable kube-apiserver kube-controller-manager kube-scheduler
Created symlink /etc/systemd/system/multi-user.target.wants/kube-apiserver.service → /etc/systemd/system/kube-apiserver.service.
Created symlink /etc/systemd/system/multi-user.target.wants/kube-controller-manager.service → /etc/systemd/system/kube-controller-manager.service.
Created symlink /etc/systemd/system/multi-user.target.wants/kube-scheduler.service → /etc/systemd/system/kube-scheduler.service.
root@server:~# systemctl start  kube-apiserver kube-controller-manager kube-scheduler

root@server:~# ss -tlp | grep kube
LISTEN 0      4096               *:6443              *:*    users:(("kube-apiserver",pid=2803,fd=3))
LISTEN 0      4096               *:10257             *:*    users:(("kube-controller",pid=2804,fd=3))
LISTEN 0      4096               *:10259             *:*    users:(("kube-scheduler",pid=2809,fd=3))

root@server:~# systemctl is-active kube-apiserver
active
root@server:~# systemctl status kube-apiserver --no-pager
● kube-apiserver.service - Kubernetes API Server
     Loaded: loaded (/etc/systemd/system/kube-apiserver.service; enabled; preset: enabled)
     Active: active (running) since Sun 2026-01-11 08:38:14 KST; 1min 9s ago
       Docs: https://github.com/kubernetes/kubernetes
   Main PID: 2803 (kube-apiserver)
      Tasks: 9 (limit: 2096)
     Memory: 210.2M
        CPU: 3.860s
     CGroup: /system.slice/kube-apiserver.service
             └─2803 /usr/local/bin/kube-apiserver --allow-privileged=true --apiserver-count=1 --audit-log-maxage=30 --audit-log-maxbackup=3 --audit-log-maxsize=100 --audit-log-path=/var/log/…

Jan 11 08:38:17 server kube-apiserver[2803]: I0111 08:38:17.446400    2803 storage_rbac.go:321] created rolebinding.rbac.authorization.k8s.io/system:controller:cloud-provider in kube-system
Jan 11 08:38:17 server kube-apiserver[2803]: I0111 08:38:17.448425    2803 storage_rbac.go:321] created rolebinding.rbac.authorization.k8s.io/system:controller:token-cleaner in kube-system
Jan 11 08:38:17 server kube-apiserver[2803]: I0111 08:38:17.450674    2803 storage_rbac.go:321] created rolebinding.rbac.authorization.k8s.io/system:controller:bootstrap-signer in kube-public
Jan 11 08:38:17 server kube-apiserver[2803]: I0111 08:38:17.504016    2803 alloc.go:330] "allocated clusterIPs" service="default/kubernetes" clusterIPs={"IPv4":"10.32.0.1"}
Jan 11 08:38:17 server kube-apiserver[2803]: W0111 08:38:17.506560    2803 lease.go:265] Resetting endpoints for master service "kubernetes" to [10.0.2.15]
Jan 11 08:38:17 server kube-apiserver[2803]: I0111 08:38:17.507060    2803 controller.go:615] quota admission added evaluator for: endpoints
Jan 11 08:38:17 server kube-apiserver[2803]: I0111 08:38:17.510095    2803 controller.go:615] quota admission added evaluator for: endpointslices.discovery.k8s.io
Jan 11 08:38:20 server kube-apiserver[2803]: I0111 08:38:20.160901    2803 controller.go:615] quota admission added evaluator for: serviceaccounts
Jan 11 08:38:26 server kube-apiserver[2803]: I0111 08:38:26.306880    2803 apf_controller.go:493] "Update CurrentCL" plName="exempt" seatDemandHighWatermark=2 seatDemandAvg=0.020429668431191…
Jan 11 08:38:36 server kube-apiserver[2803]: I0111 08:38:36.307942    2803 apf_controller.go:493] "Update CurrentCL" plName="exempt" seatDemandHighWatermark=1 seatDemandAvg=0.000540973546383…
Hint: Some lines were ellipsized, use -l to show in full.

root@server:~# systemctl status kube-scheduler --no-pager
● kube-scheduler.service - Kubernetes Scheduler
     Loaded: loaded (/etc/systemd/system/kube-scheduler.service; enabled; preset: enabled)
     Active: active (running) since Sun 2026-01-11 08:38:14 KST; 1min 32s ago
       Docs: https://github.com/kubernetes/kubernetes
   Main PID: 2809 (kube-scheduler)
      Tasks: 8 (limit: 2096)
     Memory: 15.3M
        CPU: 1.321s
     CGroup: /system.slice/kube-scheduler.service
             └─2809 /usr/local/bin/kube-scheduler --config=/etc/kubernetes/config/kube-scheduler.yaml --v=2

Jan 11 08:38:17 server kube-scheduler[2809]: I0111 08:38:17.795270    2809 reflector.go:376] Caches populated for *v1.ReplicationController from k8s.io/client-go/informers/factory.go:160
Jan 11 08:38:17 server kube-scheduler[2809]: I0111 08:38:17.816831    2809 reflector.go:376] Caches populated for *v1.CSIDriver from k8s.io/client-go/informers/factory.go:160
Jan 11 08:38:17 server kube-scheduler[2809]: I0111 08:38:17.889509    2809 reflector.go:376] Caches populated for *v1.StorageClass from k8s.io/client-go/informers/factory.go:160
Jan 11 08:38:17 server kube-scheduler[2809]: I0111 08:38:17.976799    2809 reflector.go:376] Caches populated for *v1.ReplicaSet from k8s.io/client-go/informers/factory.go:160
Jan 11 08:38:18 server kube-scheduler[2809]: I0111 08:38:18.053109    2809 reflector.go:376] Caches populated for *v1.Pod from k8s.io/client-go/informers/factory.go:160
Jan 11 08:38:18 server kube-scheduler[2809]: I0111 08:38:18.104208    2809 reflector.go:376] Caches populated for *v1.Namespace from k8s.io/client-go/informers/factory.go:160
Jan 11 08:38:18 server kube-scheduler[2809]: I0111 08:38:18.104322    2809 reflector.go:376] Caches populated for *v1.PersistentVolumeClaim from k8s.io/client-go/informers/factory.go:160
Jan 11 08:38:20 server kube-scheduler[2809]: I0111 08:38:20.518170    2809 reflector.go:376] Caches populated for *v1.PersistentVolume from k8s.io/client-go/informers/factory.go:160
Jan 11 08:38:20 server kube-scheduler[2809]: I0111 08:38:20.543776    2809 leaderelection.go:257] attempting to acquire leader lease kube-system/kube-scheduler...
Jan 11 08:38:20 server kube-scheduler[2809]: I0111 08:38:20.547972    2809 leaderelection.go:271] successfully acquired lease kube-system/kube-scheduler

root@server:~# systemctl status kube-controller-manager --no-pager
● kube-controller-manager.service - Kubernetes Controller Manager
     Loaded: loaded (/etc/systemd/system/kube-controller-manager.service; enabled; preset: enabled)
     Active: active (running) since Sun 2026-01-11 08:38:14 KST; 1min 38s ago
       Docs: https://github.com/kubernetes/kubernetes
   Main PID: 2804 (kube-controller)
      Tasks: 5 (limit: 2096)
     Memory: 40.2M
        CPU: 2.314s
     CGroup: /system.slice/kube-controller-manager.service
             └─2804 /usr/local/bin/kube-controller-manager --bind-address=0.0.0.0 --cluster-cidr=10.200.0.0/16 --cluster-name=kubernetes --cluster-signing-cert-file=/var/lib/kubernetes/ca.cr…

Jan 11 08:38:24 server kube-controller-manager[2804]: I0111 08:38:24.351097    2804 shared_informer.go:320] Caches are synced for certificate-csrsigning-kubelet-client
Jan 11 08:38:24 server kube-controller-manager[2804]: I0111 08:38:24.351083    2804 shared_informer.go:320] Caches are synced for certificate-csrsigning-legacy-unknown
Jan 11 08:38:24 server kube-controller-manager[2804]: I0111 08:38:24.351111    2804 shared_informer.go:320] Caches are synced for disruption
Jan 11 08:38:24 server kube-controller-manager[2804]: I0111 08:38:24.352466    2804 shared_informer.go:320] Caches are synced for ReplicaSet
Jan 11 08:38:24 server kube-controller-manager[2804]: I0111 08:38:24.352467    2804 shared_informer.go:320] Caches are synced for endpoint_slice
Jan 11 08:38:24 server kube-controller-manager[2804]: I0111 08:38:24.352487    2804 endpointslice_controller.go:288] "Starting service queue worker threads" logger="endpointsli…oller" total=5
Jan 11 08:38:24 server kube-controller-manager[2804]: I0111 08:38:24.352505    2804 endpointslice_controller.go:292] "Starting topology queue worker threads" logger="endpointsl…oller" total=1
Jan 11 08:38:24 server kube-controller-manager[2804]: I0111 08:38:24.352540    2804 shared_informer.go:320] Caches are synced for stateful set
Jan 11 08:38:24 server kube-controller-manager[2804]: I0111 08:38:24.353634    2804 shared_informer.go:320] Caches are synced for legacy-service-account-token-cleaner
Jan 11 08:38:24 server kube-controller-manager[2804]: I0111 08:38:24.353714    2804 shared_informer.go:320] Caches are synced for PVC protection
Hint: Some lines were ellipsized, use -l to show in full.

root@server:~# kubectl cluster-info --kubeconfig admin.kubeconfig
Kubernetes control plane is running at https://127.0.0.1:6443

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.


# kubectl 동작확인
root@server:~# kubectl get node --kubeconfig admin.kubeconfig
No resources found
root@server:~# kubectl get pod -A --kubeconfig admin.kubeconfig
No resources found
root@server:~# kubectl get service,ep --kubeconfig admin.kubeconfig
NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.32.0.1    <none>        443/TCP   2m58s

NAME                   ENDPOINTS        AGE
endpoints/kubernetes   10.0.2.15:6443   2m58s
root@server:~# kubectl get clusterroles --kubeconfig admin.kubeconfig
NAME                                                                   CREATED AT
admin                                                                  2026-01-10T23:38:17Z
cluster-admin                                                          2026-01-10T23:38:17Z
edit                                                                   2026-01-10T23:38:17Z
system:aggregate-to-admin                                              2026-01-10T23:38:17Z
system:aggregate-to-edit                                               2026-01-10T23:38:17Z
system:aggregate-to-view                                               2026-01-10T23:38:17Z
system:auth-delegator                                                  2026-01-10T23:38:17Z
system:basic-user                                                      2026-01-10T23:38:17Z
...

 

 

API Server가 워커 노드의 Kubelet API를 안전하게 호출할 수 있도록 RBAC 기반 접근 제어를 설정합니다. 이를 통해 메트릭 수집, 로그 조회, 포드 명령 실행과 같은 운영 기능을 API Server를 통해 수행할 수 있습니다.

Kubelet은 Webhook 권한 부여 모드를 사용하며, 요청에 대한 인가 판단은 SubjectAccessReview API를 통해 중앙에서 처리됩니다.

root@server:~# cat kube-apiserver-to-kubelet.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
  name: system:kube-apiserver-to-kubelet
rules:
  - apiGroups:
      - ""
    resources:
      - nodes/proxy
      - nodes/stats
      - nodes/log
      - nodes/spec
      - nodes/metrics
    verbs:
      - "*"
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: system:kube-apiserver
  namespace: ""
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:kube-apiserver-to-kubelet
subjects:
  - apiGroup: rbac.authorization.k8s.io
    kind: User
    name: kubernetesroot@server:~#

root@server:~# kubectl apply -f kube-apiserver-to-kubelet.yaml --kubeconfig admin.kubeconfig
clusterrole.rbac.authorization.k8s.io/system:kube-apiserver-to-kubelet created
clusterrolebinding.rbac.authorization.k8s.io/system:kube-apiserver created

 

 

점프 서버에서 Kubernetes 컨트롤 플레인 정상 동작 확인하겠습니다.

root@jumpbox:~/kubernetes-the-hard-way# curl -s -k --cacert ca.crt https://server.kubernetes.local:6443/version | jq
{
  "major": "1",
  "minor": "32",
  "gitVersion": "v1.32.3",
  "gitCommit": "32cc146f75aad04beaaa245a7157eb35063a9f99",
  "gitTreeState": "clean",
  "buildDate": "2025-03-11T19:52:21Z",
  "goVersion": "go1.23.6",
  "compiler": "gc",
  "platform": "linux/arm64"
}

 

 

워커 노드 부트스트래핑

node-0, node-1 노드에 runc, container networking plugins, containerd, kubelet, kube-proxy 설치하겠습니다.

root@jumpbox:~/kubernetes-the-hard-way# cat configs/10-bridge.conf | jq
{
  "cniVersion": "1.0.0",
  "name": "bridge",
  "type": "bridge",
  "bridge": "cni0",
  "isGateway": true,
  "ipMasq": true,
  "ipam": {
    "type": "host-local",
    "ranges": [
      [
        {
          "subnet": "SUBNET"
        }
      ]
    ],
    "routes": [
      {
        "dst": "0.0.0.0/0"
      }
    ]
  }
}

root@jumpbox:~/kubernetes-the-hard-way# cat configs/kubelet-config.yaml | yq # clusterDomain , clusterDNS 없어도 smoke test 까지 잘됨 -> 실습에서 coredns 미사용
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
address: "0.0.0.0"                            # kubelet HTTPS 서버 바인딩 주소 : 모든 인터페이스에서 10250 포트 수신
authentication:
  anonymous:
    enabled: false                            # 익명 인증 비활성화
  webhook:
    enabled: true                             # 인증 요청을 kube-apiserver에 위임 : ServiceAccount 토큰, bootstrap 토큰 처리 가능
  x509:                                       # kubelet에 접근하는 클라이언트 인증서 검증용 CA
    clientCAFile: "/var/lib/kubelet/ca.crt"   # (상동) 대상 : kube-apiserver, metrics-server, kubectl (직접 접근 시)
authorization:                                
  mode: Webhook                               # 인가 요청을 kube-apiserver에 위임 : Node Authorizer + RBAC 적용됨
cgroupDriver: systemd
containerRuntimeEndpoint: "unix:///var/run/containerd/containerd.sock"  # CRI 엔드포인트
enableServer: true                            # kubelet API 서버 활성화 , false면 apiserver가 kubelet 접근 불가
failSwapOn: false
maxPods: 16                                   # 노드당 최대 파드 수 16개
memorySwap:
  swapBehavior: NoSwap
port: 10250                                   # kubelet HTTPS API 포트 : 로그, exec, stats, metrics 접근에 사용
resolvConf: "/etc/resolv.conf"                # 파드에 전달할 DNS 설정 파일
registerNode: true                            # kubelet이 API 서버에 Node 객체 자동 등록
runtimeRequestTimeout: "15m"                  # CRI 요청 최대 대기 시간 : 이미지 pull, container start 등
tlsCertFile: "/var/lib/kubelet/kubelet.crt"   # TLS 서버 인증서 (kubelet 자신) : kubelet HTTPS 서버의 서버 인증서
tlsPrivateKeyFile: "/var/lib/kubelet/kubelet.key"


root@jumpbox:~/kubernetes-the-hard-way# for HOST in node-0 node-1; do
  SUBNET=$(grep ${HOST} machines.txt | cut -d " " -f 4)
  sed "s|SUBNET|$SUBNET|g" \
    configs/10-bridge.conf > 10-bridge.conf

  sed "s|SUBNET|$SUBNET|g" \
    configs/kubelet-config.yaml > kubelet-config.yaml

  scp 10-bridge.conf kubelet-config.yaml \
  root@${HOST}:~/
done
10-bridge.conf                                                                                                                                               100%  265   413.0KB/s   00:00
kubelet-config.yaml                                                                                                                                          100%  610     1.1MB/s   00:00
10-bridge.conf                                                                                                                                               100%  265   418.8KB/s   00:00
kubelet-config.yaml                                                                                                                                          100%  610     1.1MB/s   00:00

root@jumpbox:~/kubernetes-the-hard-way# ssh node-0 ls -l /root
total 8
-rw-r--r-- 1 root root 265 Jan 11 08:46 10-bridge.conf
-rw-r--r-- 1 root root 610 Jan 11 08:46 kubelet-config.yaml
root@jumpbox:~/kubernetes-the-hard-way# ssh node-1 ls -l /root
total 8
-rw-r--r-- 1 root root 265 Jan 11 08:46 10-bridge.conf
-rw-r--r-- 1 root root 610 Jan 11 08:46 kubelet-config.yaml

# 파일 확인 및 node-0/1에 전달
root@jumpbox:~/kubernetes-the-hard-way# cat configs/99-loopback.conf ; echo
{
  "cniVersion": "1.1.0",
  "name": "lo",
  "type": "loopback"
}
root@jumpbox:~/kubernetes-the-hard-way# cat configs/containerd-config.toml ; echo
version = 2

[plugins."io.containerd.grpc.v1.cri"]
  [plugins."io.containerd.grpc.v1.cri".containerd]
    snapshotter = "overlayfs"
    default_runtime_name = "runc"
  [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
    runtime_type = "io.containerd.runc.v2"
  [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
    SystemdCgroup = true
[plugins."io.containerd.grpc.v1.cri".cni]
  bin_dir = "/opt/cni/bin"
  conf_dir = "/etc/cni/net.d"
root@jumpbox:~/kubernetes-the-hard-way# cat configs/kube-proxy-config.yaml ; echo
kind: KubeProxyConfiguration
apiVersion: kubeproxy.config.k8s.io/v1alpha1
clientConnection:
  kubeconfig: "/var/lib/kube-proxy/kubeconfig"
mode: "iptables"
clusterCIDR: "10.200.0.0/16"

root@jumpbox:~/kubernetes-the-hard-way# cat units/containerd.service
[Unit]
Description=containerd container runtime
Documentation=https://containerd.io
After=network.target

[Service]
ExecStartPre=/sbin/modprobe overlay
ExecStart=/bin/containerd
Restart=always
RestartSec=5
Delegate=yes
KillMode=process
OOMScoreAdjust=-999
LimitNOFILE=1048576
LimitNPROC=infinity
LimitCORE=infinity

[Install]
WantedBy=multi-user.target
root@jumpbox:~/kubernetes-the-hard-way# cat units/kubelet.service
[Unit]
Description=Kubernetes Kubelet
Documentation=https://github.com/kubernetes/kubernetes
After=containerd.service
Requires=containerd.service

[Service]
ExecStart=/usr/local/bin/kubelet \
  --config=/var/lib/kubelet/kubelet-config.yaml \
  --kubeconfig=/var/lib/kubelet/kubeconfig \
  --v=2
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
root@jumpbox:~/kubernetes-the-hard-way# cat units/kube-proxy.service
[Unit]
Description=Kubernetes Kube Proxy
Documentation=https://github.com/kubernetes/kubernetes

[Service]
ExecStart=/usr/local/bin/kube-proxy \
  --config=/var/lib/kube-proxy/kube-proxy-config.yaml
Restart=on-failure
RestartSec=5

[Install]


root@jumpbox:~/kubernetes-the-hard-way# for HOST in node-0 node-1; do
  scp \
    downloads/worker/* \
    downloads/client/kubectl \
    configs/99-loopback.conf \
    configs/containerd-config.toml \
    configs/kube-proxy-config.yaml \
    units/containerd.service \
    units/kubelet.service \
    units/kube-proxy.service \
    root@${HOST}:~/
done
containerd                                                                                                                                                   100%   54MB 109.8MB/s   00:00
containerd-shim-runc-v2                                                                                                                                      100% 7808KB 115.1MB/s   00:00
containerd-stress                                                                                                                                            100%   21MB 134.4MB/s   00:00
crictl                                                                                                                                                       100%   37MB 126.0MB/s   00:00
ctr                                                                                                                                                          100%   22MB 128.0MB/s   00:00
kubelet                                                                                                                                                      100%   72MB 114.6MB/s   00:00
kube-proxy                                                                                                                                                   100%   62MB 107.7MB/s   00:00
runc                                                                                                                                                         100%   11MB 116.3MB/s   00:00
kubectl                                                                                                                                                      100%   53MB  99.3MB/s   00:00
99-loopback.conf                                                                                                                                             100%   65   144.9KB/s   00:00
containerd-config.toml                                                                                                                                       100%  470     1.1MB/s   00:00
kube-proxy-config.yaml                                                                                                                                       100%  184   431.0KB/s   00:00
containerd.service                                                                                                                                           100%  352   739.2KB/s   00:00
kubelet.service                                                                                                                                              100%  365   781.0KB/s   00:00
kube-proxy.service                                                                                                                                           100%  268   498.2KB/s   00:00
containerd                                                                                                                                                   100%   54MB 123.9MB/s   00:00
containerd-shim-runc-v2                                                                                                                                      100% 7808KB 123.9MB/s   00:00
containerd-stress                                                                                                                                            100%   21MB 128.7MB/s   00:00
crictl                                                                                                                                                       100%   37MB 129.9MB/s   00:00
ctr                                                                                                                                                          100%   22MB 127.6MB/s   00:00
kubelet                                                                                                                                                      100%   72MB 121.1MB/s   00:00
kube-proxy                                                                                                                                                   100%   62MB 103.1MB/s   00:00
runc                                                                                                                                                         100%   11MB 132.1MB/s   00:00
kubectl                                                                                                                                                      100%   53MB 114.7MB/s   00:00
99-loopback.conf                                                                                                                                             100%   65   116.5KB/s   00:00
containerd-config.toml                                                                                                                                       100%  470   715.5KB/s   00:00
kube-proxy-config.yaml                                                                                                                                       100%  184   204.4KB/s   00:00
containerd.service                                                                                                                                           100%  352   716.2KB/s   00:00
kubelet.service                                                                                                                                              100%  365   684.7KB/s   00:00
kube-proxy.service                                                                                                                                           100%  268   366.2KB/s   00:00

root@jumpbox:~/kubernetes-the-hard-way# for HOST in node-0 node-1; do
  scp \
    downloads/cni-plugins/* \
    root@${HOST}:~/cni-plugins/
done
bandwidth                                                                                                                                                    100% 4492KB  52.1MB/s   00:00
bridge                                                                                                                                                       100% 5065KB 107.0MB/s   00:00
dhcp                                                                                                                                                         100%   12MB 102.8MB/s   00:00
dummy                                                                                                                                                        100% 4623KB 108.5MB/s   00:00
firewall                                                                                                                                                     100% 5088KB 144.1MB/s   00:00
host-device                                                                                                                                                  100% 4611KB 119.7MB/s   00:00
host-local                                                                                                                                                   100% 3886KB 113.2MB/s   00:00
ipvlan                                                                                                                                                       100% 4628KB 114.8MB/s   00:00
LICENSE                                                                                                                                                      100%   11KB  14.6MB/s   00:00
loopback                                                                                                                                                     100% 4030KB 126.9MB/s   00:00
macvlan                                                                                                                                                      100% 4764KB 110.9MB/s   00:00
portmap                                                                                                                                                      100% 4513KB  88.0MB/s   00:00
ptp                                                                                                                                                          100% 4877KB 113.8MB/s   00:00
README.md                                                                                                                                                    100% 2343     3.3MB/s   00:00
sbr                                                                                                                                                          100% 4216KB 113.4MB/s   00:00
static                                                                                                                                                       100% 3498KB 110.7MB/s   00:00
tap                                                                                                                                                          100% 4775KB 122.1MB/s   00:00
tuning                                                                                                                                                       100% 4054KB 108.8MB/s   00:00
vlan                                                                                                                                                         100% 4627KB  80.0MB/s   00:00
vrf                                                                                                                                                          100% 4325KB 116.8MB/s   00:00
bandwidth                                                                                                                                                    100% 4492KB  64.0MB/s   00:00
bridge                                                                                                                                                       100% 5065KB 140.7MB/s   00:00
dhcp                                                                                                                                                         100%   12MB 128.4MB/s   00:00
dummy                                                                                                                                                        100% 4623KB 134.0MB/s   00:00
firewall                                                                                                                                                     100% 5088KB 134.2MB/s   00:00
host-device                                                                                                                                                  100% 4611KB 130.3MB/s   00:00
host-local                                                                                                                                                   100% 3886KB 137.3MB/s   00:00
ipvlan                                                                                                                                                       100% 4628KB 135.9MB/s   00:00
LICENSE                                                                                                                                                      100%   11KB  18.1MB/s   00:00
loopback                                                                                                                                                     100% 4030KB 113.2MB/s   00:00
macvlan                                                                                                                                                      100% 4764KB 124.8MB/s   00:00
portmap                                                                                                                                                      100% 4513KB 124.5MB/s   00:00
ptp                                                                                                                                                          100% 4877KB 129.0MB/s   00:00
README.md                                                                                                                                                    100% 2343     4.5MB/s   00:00
sbr                                                                                                                                                          100% 4216KB 127.5MB/s   00:00
static                                                                                                                                                       100% 3498KB 135.4MB/s   00:00
tap                                                                                                                                                          100% 4775KB 134.7MB/s   00:00
tuning                                                                                                                                                       100% 4054KB 137.7MB/s   00:00
vlan                                                                                                                                                         100% 4627KB 140.3MB/s   00:00
vrf                                                                                                                                                          100% 4325KB 136.6MB/s   00:00


root@jumpbox:~/kubernetes-the-hard-way# ssh node-0 ls -l /root
total 347860
-rw-r--r-- 1 root root      265 Jan 11 08:46 10-bridge.conf
-rw-r--r-- 1 root root       65 Jan 11 08:51 99-loopback.conf
drwxr-xr-x 2 root root     4096 Jan 11 08:51 cni-plugins
-rwxr-xr-x 1 root root 56836190 Jan 11 08:51 containerd
-rw-r--r-- 1 root root      470 Jan 11 08:51 containerd-config.toml
-rw-r--r-- 1 root root      352 Jan 11 08:51 containerd.service
-rwxr-xr-x 1 root root  7995576 Jan 11 08:51 containerd-shim-runc-v2
-rwxr-xr-x 1 root root 22020449 Jan 11 08:51 containerd-stress
-rwxr-xr-x 1 root root 38808389 Jan 11 08:51 crictl
-rwxr-xr-x 1 root root 22806881 Jan 11 08:51 ctr
-rwxr-xr-x 1 root root 55836824 Jan 11 08:51 kubectl
-rwxr-xr-x 1 root root 75235588 Jan 11 08:51 kubelet
-rw-r--r-- 1 root root      610 Jan 11 08:46 kubelet-config.yaml
-rw-r--r-- 1 root root      365 Jan 11 08:51 kubelet.service
-rwxr-xr-x 1 root root 65274008 Jan 11 08:51 kube-proxy
-rw-r--r-- 1 root root      184 Jan 11 08:51 kube-proxy-config.yaml
-rw-r--r-- 1 root root      268 Jan 11 08:51 kube-proxy.service
-rwxr-xr-x 1 root root 11305168 Jan 11 08:51 runc
root@jumpbox:~/kubernetes-the-hard-way# ssh node-1 ls -l /root
total 347860
-rw-r--r-- 1 root root      265 Jan 11 08:46 10-bridge.conf
-rw-r--r-- 1 root root       65 Jan 11 08:51 99-loopback.conf
drwxr-xr-x 2 root root     4096 Jan 11 08:51 cni-plugins
-rwxr-xr-x 1 root root 56836190 Jan 11 08:51 containerd
-rw-r--r-- 1 root root      470 Jan 11 08:51 containerd-config.toml
-rw-r--r-- 1 root root      352 Jan 11 08:51 containerd.service
-rwxr-xr-x 1 root root  7995576 Jan 11 08:51 containerd-shim-runc-v2
-rwxr-xr-x 1 root root 22020449 Jan 11 08:51 containerd-stress
-rwxr-xr-x 1 root root 38808389 Jan 11 08:51 crictl
-rwxr-xr-x 1 root root 22806881 Jan 11 08:51 ctr
-rwxr-xr-x 1 root root 55836824 Jan 11 08:51 kubectl
-rwxr-xr-x 1 root root 75235588 Jan 11 08:51 kubelet
-rw-r--r-- 1 root root      610 Jan 11 08:46 kubelet-config.yaml
-rw-r--r-- 1 root root      365 Jan 11 08:51 kubelet.service
-rwxr-xr-x 1 root root 65274008 Jan 11 08:51 kube-proxy
-rw-r--r-- 1 root root      184 Jan 11 08:51 kube-proxy-config.yaml
-rw-r--r-- 1 root root      268 Jan 11 08:51 kube-proxy.service
-rwxr-xr-x 1 root root 11305168 Jan 11 08:51 runc
root@jumpbox:~/kubernetes-the-hard-way# ssh node-0 ls -l /root/cni-plugins
total 88164
-rwxr-xr-x 1 root root  4600029 Jan 11 08:51 bandwidth
-rwxr-xr-x 1 root root  5186762 Jan 11 08:51 bridge
-rwxr-xr-x 1 root root 12321657 Jan 11 08:51 dhcp
-rwxr-xr-x 1 root root  4734102 Jan 11 08:51 dummy
-rwxr-xr-x 1 root root  5210586 Jan 11 08:51 firewall
-rwxr-xr-x 1 root root  4721690 Jan 11 08:51 host-device
-rwxr-xr-x 1 root root  3979580 Jan 11 08:51 host-local
-rwxr-xr-x 1 root root  4738895 Jan 11 08:51 ipvlan
-rwxr-xr-x 1 root root    11357 Jan 11 08:51 LICENSE
-rwxr-xr-x 1 root root  4127141 Jan 11 08:51 loopback
-rwxr-xr-x 1 root root  4878636 Jan 11 08:51 macvlan
-rwxr-xr-x 1 root root  4621227 Jan 11 08:51 portmap
-rwxr-xr-x 1 root root  4994381 Jan 11 08:51 ptp
-rwxr-xr-x 1 root root     2343 Jan 11 08:51 README.md
-rwxr-xr-x 1 root root  4317592 Jan 11 08:51 sbr
-rwxr-xr-x 1 root root  3582221 Jan 11 08:51 static
-rwxr-xr-x 1 root root  4889353 Jan 11 08:51 tap
-rwxr-xr-x 1 root root  4150810 Jan 11 08:51 tuning
-rwxr-xr-x 1 root root  4738028 Jan 11 08:51 vlan
-rwxr-xr-x 1 root root  4428332 Jan 11 08:51 vrf
root@jumpbox:~/kubernetes-the-hard-way# ssh node-1 ls -l /root/cni-plugins
total 88164
-rwxr-xr-x 1 root root  4600029 Jan 11 08:51 bandwidth
-rwxr-xr-x 1 root root  5186762 Jan 11 08:51 bridge
-rwxr-xr-x 1 root root 12321657 Jan 11 08:51 dhcp
-rwxr-xr-x 1 root root  4734102 Jan 11 08:51 dummy
-rwxr-xr-x 1 root root  5210586 Jan 11 08:51 firewall
-rwxr-xr-x 1 root root  4721690 Jan 11 08:51 host-device
-rwxr-xr-x 1 root root  3979580 Jan 11 08:51 host-local
-rwxr-xr-x 1 root root  4738895 Jan 11 08:51 ipvlan
-rwxr-xr-x 1 root root    11357 Jan 11 08:51 LICENSE
-rwxr-xr-x 1 root root  4127141 Jan 11 08:51 loopback
-rwxr-xr-x 1 root root  4878636 Jan 11 08:51 macvlan
-rwxr-xr-x 1 root root  4621227 Jan 11 08:51 portmap
-rwxr-xr-x 1 root root  4994381 Jan 11 08:51 ptp
-rwxr-xr-x 1 root root     2343 Jan 11 08:51 README.md
-rwxr-xr-x 1 root root  4317592 Jan 11 08:51 sbr
-rwxr-xr-x 1 root root  3582221 Jan 11 08:51 static
-rwxr-xr-x 1 root root  4889353 Jan 11 08:51 tap
-rwxr-xr-x 1 root root  4150810 Jan 11 08:51 tuning
-rwxr-xr-x 1 root root  4738028 Jan 11 08:51 vlan
-rwxr-xr-x 1 root root  4428332 Jan 11 08:51 vrf

 

워커노드 프로비저닝을 위해 node-0, node-1에 접속하여 실행하겠습니다.

# kubelet ↔ containerd 연결 Flow
kubelet
  ↓ CRI (gRPC)
unix:///var/run/containerd/containerd.sock
  ↓
containerd CRI plugin
  ↓
runc
  ↓
Linux namespaces / cgroups

 

# Node 0 접속 후 실행 (Node 1도 동일)
root@jumpbox:~/kubernetes-the-hard-way# ssh root@node-0
root@node-0:~# apt-get -y install socat conntrack ipset kmod psmisc bridge-utils
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
kmod is already the newest version (30+20221128-1).
The following additional packages will be installed:
  iptables libip6tc2 libipset13 libnetfilter-conntrack3 libnfnetlink0
  ...
  
# Disable Swap : Verify if swap is disabled:
root@node-0:~# swapon --show

# Create the installation directories
root@node-0:~# mkdir -p \
  /etc/cni/net.d \
  /opt/cni/bin \
  /var/lib/kubelet \
  /var/lib/kube-proxy \
  /var/lib/kubernetes \
  /var/run/kubernetes

# Install the worker binaries:
root@node-0:~# mv crictl kube-proxy kubelet runc /usr/local/bin/
root@node-0:~# mv containerd containerd-shim-runc-v2 containerd-stress /bin/
root@node-0:~# mv cni-plugins/* /opt/cni/bin/

# Configure CNI Networking

# Create the bridge network configuration file:
root@node-0:~# mv 10-bridge.conf 99-loopback.conf /etc/cni/net.d/
root@node-0:~# cat /etc/cni/net.d/10-bridge.conf
{
  "cniVersion": "1.0.0",
  "name": "bridge",
  "type": "bridge",
  "bridge": "cni0",
  "isGateway": true,
  "ipMasq": true,
  "ipam": {
    "type": "host-local",
    "ranges": [
      [{"subnet": "10.200.0.0/24"}]
    ],
    "routes": [{"dst": "0.0.0.0/0"}]
  }
}

# To ensure network traffic crossing the CNI bridge network is processed by iptables, load and configure the br-netfilter kernel module:
root@node-0:~# lsmod | grep netfilter
root@node-0:~# modprobe br-netfilter
root@node-0:~# echo "br-netfilter" >> /etc/modules-load.d/modules.conf
root@node-0:~# lsmod | grep netfilter
br_netfilter           32768  0
bridge                262144  1 br_netfilter

root@node-0:~# echo "net.bridge.bridge-nf-call-iptables = 1"  >> /etc/sysctl.d/kubernetes.conf
root@node-0:~# echo "net.bridge.bridge-nf-call-ip6tables = 1" >> /etc/sysctl.d/kubernetes.conf
root@node-0:~# sysctl -p /etc/sysctl.d/kubernetes.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1


# Configure containerd : Install the containerd configuration files:
root@node-0:~# mkdir -p /etc/containerd/
root@node-0:~# mv containerd-config.toml /etc/containerd/config.toml
root@node-0:~# mv containerd.service /etc/systemd/system/
root@node-0:~# cat /etc/containerd/config.toml ; echo
version = 2

[plugins."io.containerd.grpc.v1.cri"]               # CRI 플러그인 활성화 : kubelet은 이 플러그인을 통해 containerd와 통신
  [plugins."io.containerd.grpc.v1.cri".containerd]  # containerd 기본 런타임 설정
    snapshotter = "overlayfs"                       # 컨테이너 파일시스템 레이어 관리 방식 : Linux표준/성능최적
    default_runtime_name = "runc"                   # 기본 OCI 런타임 : 파드가 별도 지정 없을 경우 runc 사용
  [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]  # runc 런타임 상세 설정
    runtime_type = "io.containerd.runc.v2"                        # containerd 최신 runc shim
  [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]  # runc 옵션
    SystemdCgroup = true                                                  # containerd가 cgroup을 systemd로 관리 
[plugins."io.containerd.grpc.v1.cri".cni]           # CNI 설정
  bin_dir = "/opt/cni/bin"                          # CNI 플러그인 바이너리 위치
  conf_dir = "/etc/cni/net.d"                       # CNI 네트워크 설정 파일 위치
  
  
# Configure the Kubelet : Create the kubelet-config.yaml configuration file:
root@node-0:~# mv kubelet-config.yaml /var/lib/kubelet/
root@node-0:~# mv kubelet.service /etc/systemd/system/

# Configure the Kubernetes Proxy
root@node-0:~# mv kube-proxy-config.yaml /var/lib/kube-proxy/
root@node-0:~# mv kube-proxy.service /etc/systemd/system/

# Start the Worker Services
root@node-0:~# systemctl daemon-reload
root@node-0:~# systemctl enable containerd kubelet kube-proxy
Created symlink /etc/systemd/system/multi-user.target.wants/containerd.service → /etc/systemd/system/containerd.service.
Created symlink /etc/systemd/system/multi-user.target.wants/kubelet.service → /etc/systemd/system/kubelet.service.
Created symlink /etc/systemd/system/multi-user.target.wants/kube-proxy.service → /etc/systemd/system/kube-proxy.service.
root@node-0:~# systemctl start containerd kubelet kube-proxy

# 확인
root@node-0:~# systemctl status kubelet --no-pager
● kubelet.service - Kubernetes Kubelet
     Loaded: loaded (/etc/systemd/system/kubelet.service; enabled; preset: enabled)
     Active: active (running) since Sun 2026-01-11 08:59:02 KST; 4s ago
       Docs: https://github.com/kubernetes/kubernetes
   Main PID: 2937 (kubelet)
      Tasks: 11 (limit: 2096)
     Memory: 24.5M
        CPU: 277ms
     CGroup: /system.slice/kubelet.service
             └─2937 /usr/local/bin/kubelet --config=/var/lib/kubelet/kubelet-config.yaml --kubeconfig=/var/lib/kubelet/kubeconfig --v=2

Jan 11 08:59:02 node-0 kubelet[2937]: I0111 08:59:02.425947    2937 kubelet_node_status.go:687] "Recording event message for node" node="node-0" event="NodeHasNoDiskPressure"
Jan 11 08:59:02 node-0 kubelet[2937]: I0111 08:59:02.425955    2937 kubelet_node_status.go:687] "Recording event message for node" node="node-0" event="NodeHasSufficientPID"
Jan 11 08:59:02 node-0 kubelet[2937]: I0111 08:59:02.426436    2937 kubelet_node_status.go:75] "Attempting to register node" node="node-0"
Jan 11 08:59:02 node-0 kubelet[2937]: I0111 08:59:02.432949    2937 kubelet_node_status.go:78] "Successfully registered node" node="node-0"
Jan 11 08:59:02 node-0 kubelet[2937]: I0111 08:59:02.655470    2937 kubelet_node_status.go:687] "Recording event message for node" node="node-0" event="NodeReady"
Jan 11 08:59:02 node-0 kubelet[2937]: I0111 08:59:02.655542    2937 kubelet_node_status.go:501] "Fast updating node status as it just became ready"
Jan 11 08:59:03 node-0 kubelet[2937]: I0111 08:59:03.201514    2937 apiserver.go:52] "Watching apiserver"
Jan 11 08:59:03 node-0 kubelet[2937]: I0111 08:59:03.204673    2937 reflector.go:376] Caches populated for *v1.Pod from pkg/kubelet/config/apiserver.go:66
Jan 11 08:59:03 node-0 kubelet[2937]: I0111 08:59:03.204949    2937 kubelet.go:2468] "SyncLoop ADD" source="api" pods=[]
Jan 11 08:59:03 node-0 kubelet[2937]: I0111 08:59:03.213472    2937 desired_state_of_world_populator.go:157] "Finished populating initial desired state of world"
root@node-0:~# systemctl status containerd --no-pager
● containerd.service - containerd container runtime
     Loaded: loaded (/etc/systemd/system/containerd.service; enabled; preset: enabled)
     Active: active (running) since Sun 2026-01-11 08:59:02 KST; 7s ago
       Docs: https://containerd.io
    Process: 2929 ExecStartPre=/sbin/modprobe overlay (code=exited, status=0/SUCCESS)
   Main PID: 2936 (containerd)
      Tasks: 8 (limit: 2096)
     Memory: 17.8M
        CPU: 128ms
     CGroup: /system.slice/containerd.service
             └─2936 /bin/containerd

Jan 11 08:59:02 node-0 containerd[2936]: time="2026-01-11T08:59:02.179211032+09:00" level=info msg="Start event monitor"
Jan 11 08:59:02 node-0 containerd[2936]: time="2026-01-11T08:59:02.179221574+09:00" level=info msg="Start cni network conf syncer for default"
Jan 11 08:59:02 node-0 containerd[2936]: time="2026-01-11T08:59:02.179226490+09:00" level=info msg="Start streaming server"
Jan 11 08:59:02 node-0 containerd[2936]: time="2026-01-11T08:59:02.179238532+09:00" level=info msg="Registered namespace \"k8s.io\" with NRI"
Jan 11 08:59:02 node-0 containerd[2936]: time="2026-01-11T08:59:02.179244282+09:00" level=info msg="runtime interface starting up..."
Jan 11 08:59:02 node-0 containerd[2936]: time="2026-01-11T08:59:02.179248324+09:00" level=info msg="starting plugins..."
Jan 11 08:59:02 node-0 containerd[2936]: time="2026-01-11T08:59:02.179258740+09:00" level=info msg="Synchronizing NRI (plugin) with current runtime state"
Jan 11 08:59:02 node-0 containerd[2936]: time="2026-01-11T08:59:02.179524407+09:00" level=info msg=serving... address=/run/containerd/containerd.sock.ttrpc
Jan 11 08:59:02 node-0 containerd[2936]: time="2026-01-11T08:59:02.180191990+09:00" level=info msg=serving... address=/run/containerd/containerd.sock
Jan 11 08:59:02 node-0 containerd[2936]: time="2026-01-11T08:59:02.180276824+09:00" level=info msg="containerd successfully booted in 0.080985s"
root@node-0:~# systemctl status kube-proxy --no-pager
● kube-proxy.service - Kubernetes Kube Proxy
     Loaded: loaded (/etc/systemd/system/kube-proxy.service; enabled; preset: enabled)
     Active: active (running) since Sun 2026-01-11 08:59:02 KST; 10s ago
       Docs: https://github.com/kubernetes/kubernetes
   Main PID: 2930 (kube-proxy)
      Tasks: 5 (limit: 2096)
     Memory: 14.2M
        CPU: 282ms
     CGroup: /system.slice/kube-proxy.service
             └─2930 /usr/local/bin/kube-proxy --config=/var/lib/kube-proxy/kube-proxy-config.yaml

Jan 11 08:59:03 node-0 kube-proxy[2930]: I0111 08:59:03.470716    2930 server.go:499] "Golang settings" GOGC="" GOMAXPROCS="" GOTRACEBACK=""
Jan 11 08:59:03 node-0 kube-proxy[2930]: I0111 08:59:03.474823    2930 config.go:199] "Starting service config controller"
Jan 11 08:59:03 node-0 kube-proxy[2930]: I0111 08:59:03.474988    2930 shared_informer.go:313] Waiting for caches to sync for service config
Jan 11 08:59:03 node-0 kube-proxy[2930]: I0111 08:59:03.475123    2930 config.go:329] "Starting node config controller"
Jan 11 08:59:03 node-0 kube-proxy[2930]: I0111 08:59:03.475178    2930 shared_informer.go:313] Waiting for caches to sync for node config
Jan 11 08:59:03 node-0 kube-proxy[2930]: I0111 08:59:03.475453    2930 config.go:105] "Starting endpoint slice config controller"
Jan 11 08:59:03 node-0 kube-proxy[2930]: I0111 08:59:03.475478    2930 shared_informer.go:313] Waiting for caches to sync for endpoint slice config
Jan 11 08:59:03 node-0 kube-proxy[2930]: I0111 08:59:03.575744    2930 shared_informer.go:320] Caches are synced for node config
Jan 11 08:59:03 node-0 kube-proxy[2930]: I0111 08:59:03.575765    2930 shared_informer.go:320] Caches are synced for endpoint slice config
Jan 11 08:59:03 node-0 kube-proxy[2930]: I0111 08:59:03.575802    2930 shared_informer.go:320] Caches are synced for service config

 

원격 접근을 위한 kubectl 설정

jumpbox 노드에서 kubectl을 admin 자격 증명으로 사용을 위한 설정을 구성합니다.

# You should be able to ping server.kubernetes.local based on the /etc/hosts DNS entry from a previous lab.
root@jumpbox:~/kubernetes-the-hard-way# curl -s --cacert ca.crt https://server.kubernetes.local:6443/version | jq
{
  "major": "1",
  "minor": "32",
  "gitVersion": "v1.32.3",
  "gitCommit": "32cc146f75aad04beaaa245a7157eb35063a9f99",
  "gitTreeState": "clean",
  "buildDate": "2025-03-11T19:52:21Z",
  "goVersion": "go1.23.6",
  "compiler": "gc",
  "platform": "linux/arm64"
}

# Generate a kubeconfig file suitable for authenticating as the admin user:
root@jumpbox:~/kubernetes-the-hard-way# kubectl config set-cluster kubernetes-the-hard-way \
  --certificate-authority=ca.crt \
  --embed-certs=true \
  --server=https://server.kubernetes.local:6443
Cluster "kubernetes-the-hard-way" set.

root@jumpbox:~/kubernetes-the-hard-way# kubectl config set-credentials admin \
  --client-certificate=admin.crt \
  --client-key=admin.key
User "admin" set.

root@jumpbox:~/kubernetes-the-hard-way# kubectl config set-context kubernetes-the-hard-way \
  --cluster=kubernetes-the-hard-way \
  --user=admin
Context "kubernetes-the-hard-way" created.

root@jumpbox:~/kubernetes-the-hard-way# kubectl config use-context kubernetes-the-hard-way
Switched to context "kubernetes-the-hard-way".

root@jumpbox:~/kubernetes-the-hard-way# kubectl version
Client Version: v1.32.3
Kustomize Version: v5.5.0
Server Version: v1.32.3
root@jumpbox:~/kubernetes-the-hard-way#
root@jumpbox:~/kubernetes-the-hard-way# kubectl get nodes -v=6
I0111 09:20:48.852866    3046 loader.go:402] Config loaded from file:  /root/.kube/config
I0111 09:20:48.853973    3046 envvar.go:172] "Feature gate default state" feature="ClientsAllowCBOR" enabled=false
I0111 09:20:48.854086    3046 envvar.go:172] "Feature gate default state" feature="ClientsPreferCBOR" enabled=false
I0111 09:20:48.854173    3046 envvar.go:172] "Feature gate default state" feature="InformerResourceVersion" enabled=false
I0111 09:20:48.854255    3046 envvar.go:172] "Feature gate default state" feature="WatchListClient" enabled=false
I0111 09:20:48.854156    3046 cert_rotation.go:140] Starting client certificate rotation controller
I0111 09:20:48.878114    3046 round_trippers.go:560] GET https://server.kubernetes.local:6443/api?timeout=32s 200 OK in 23 milliseconds
I0111 09:20:48.880569    3046 round_trippers.go:560] GET https://server.kubernetes.local:6443/apis?timeout=32s 200 OK in 1 milliseconds
I0111 09:20:48.893465    3046 round_trippers.go:560] GET https://server.kubernetes.local:6443/api/v1/nodes?limit=500 200 OK in 2 milliseconds
NAME     STATUS   ROLES    AGE     VERSION
node-0   Ready    <none>   21m     v1.32.3
node-1   Ready    <none>   2m15s   v1.32.3

root@jumpbox:~/kubernetes-the-hard-way# cat /root/.kube/config
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUZURENDQXpTZ0F3SUJBZ0lVY1NNVHR5S29XcXlkK1lYWUZqVVZhd05pT2prd0RRWUpLb1pJaHZjTkFRRU4KQlFBd1FURUxNQWtHQTFVRUJoTUNWVk14RXpBUkJnTlZCQWdNQ2xkaGMyaHBibWQwYjI0eEVEQU9CZ05WQkFjTQpCMU5sWVhSMGJHVXhDekFKQmdOVkJBTU1Ba05CTUI0WERUSTJNREV4TURJeU1EVTFObG9YRFRNMk1ERXhNVEl5Ck1EVTFObG93UVRFTE1Ba0dBMVVFQmhNQ1ZWTXhFekFSQmdOVkJBZ01DbGRoYzJocGJtZDBiMjR4RURBT0JnTlYKQkFjTUIxTmxZWFIwYkdVeEN6QUpCZ05WQkFNTUFrTkJNSUlDSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQWc4QQpNSUlDQ2dLQ0FnRUFudE4xUGh0Q3lCZ0dYUnBWeHViaUp6emhTOStVUUpiUEgxeWd4WTNrOVVlQmZnV1YvSmxRCjBmWk1ib294aXMyYzVBR1B1SnpZbW9UbkZtZjNxRWdVY09Rc0ZVYlNGSWtSU1FOQW9JMmRUdk1ESUVLNXgrK3gKazZxN1luaVhHWFFEN3R3QUdON2dvdGt4NjNGSDBPbEJNb0tBR05QcTBNZHFGMEVacktxdXlUQ1paU09yRHNjawo2bysycGxJNWVlTmg1YzBFaUFFTmxZdFc5UVd5enJDOFZLOWNYR0hDU1hqemhUc05KQUY2a0ZvNWFUTWZtRjdDCnhBTFRqSlFpc0o0VkpZdytHdVRkS2FnME00b0svTXQySkxlcElJeGl4dCtQTUpGNWdLeGpVdDVUMmE4emZ1NkwKQlQ5UEs3VGQydWd1TEdGTzh1dEJhT0U4T0NZYzZmMGdscVJ0ZHJHSUF6dXZBNk9LZlJYMGdQQ2N4bzY3UVRQeQpMdENaRUVlWnlvV3ZoRVNRVUxuYzNINVBzVzkwMndvdEU0L0ovRzIwNzhkNlhUZzRWNS9wUzhUNDQ5Q20yZXd1Cld5bzZNc1FZMllWbUdIdzBxTDhMZ2dDRDlNVHF2QTFoWVBzOGo0NjZxUldic01nNTFoRmxXazZ5b081RS9INXcKVUhuQlQrTHVWb3RpOXBRNC9oWjg3aDZNc0NsT3lDK2xFM0ZJMlkvU0FwamZXS0Y5dHVJaHhmY3J3dW5wcnUrTAorZFY5eDZ5em45SS9xQjhadmFLeTFuS0g2RU53RG5PN2llN0YrNTFnb2FacTBFV2UrSHg1ZzJFcHUwZlArdlBPCnUrSzB5bUxCaVhhVGJBS0NTTW9vNFpab3BRQjBBTVVrb3NzNkgxYzZSRjV3bDZabFlreXcrWkVDQXdFQUFhTTgKTURvd0RBWURWUjBUQkFVd0F3RUIvekFMQmdOVkhROEVCQU1DQVFZd0hRWURWUjBPQkJZRUZKN05Ocm9pYTBPbgoyeU1wbDFNYjBYTGZiV0hTTUEwR0NTcUdTSWIzRFFFQkRRVUFBNElDQVFCd3ByOCs4bmlHRTlVakFLUUcyQU5rCnh6SG5NUFFOeU44NXpFcXJCMFp4M2tpSEJ0RS9GaHpRdHhoL0lkZnozRTN0U0k4blRNbTRsSDYycnZQdmM1NEYKMTlLMWdXV3poeExrWkMrdEsyMEpVVVN5dVJkS0VlTzZTSHB0UVlwOEZkTWVhWVlMSS9jSHVBcmRTNkw5ek1pYQpCTDRZWEdwbTFxM3lYeVRrd3VnSFJTcFlxeUJ6UDhMa3NESjU3T2EyYSs3Q0xaYXU1ZnczSkpPRFJEc3V5OXRUClhGS2UzT2VWQS9INmcvQUMwUzlKa1JDTnVKODhxOG40S0hDRTRySzA2dUErVklUaHltd1p0dHlsTkhDQUVGNncKa2ptbjQ1SndIS3ZSY2YybTVhZDlVNWNWd0p5bkJidnZXNi9lMXFOVGgyZnRvcEUvUVVraHozUk8vNWlMQ3BIQgpNUjZWZW5qY05FYTg2TnoyUTVWOFRmLzhSWHpOWjZHU1BBQXhsUENTNDNkWkpMZVZUc2N2bTBURlZzRm5kQktxCmlOWXZjUGxyWHp0diswTVJxOXpkVWpQS1g2by85L2RBOXkxZG9GQlBRMWFxRWhnUGRWQnJqenJNbjdXaUVna2cKZWF4VlZaYnovbXNxYUF1akZnRUdaZ2V5OEFWUEI3WWNKSit5dXFSV2xMbmJ0enl2MUt6WGd1SytYYjZBazRFdAp5T2pscWhINlNKNm9JODA3MldwcXp5Z2hEcG9IOWt5VGpILy8xSEVLNVZOdXUxbUYxMGVrd05VQk9wQkREdXl5CjNDS20xUmhkUHlYRjhtSUxwOU9FODBrb3E1SzZ0RndOUy9oREVSdFFXdC9zMUN2dHFLa1NxZFlSVUlzKzBzcXQKWVRCZTJIdWJZVGptaUdOMzhOZnlOQT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
    server: https://server.kubernetes.local:6443
  name: kubernetes-the-hard-way
contexts:
- context:
    cluster: kubernetes-the-hard-way
    user: admin
  name: kubernetes-the-hard-way
current-context: kubernetes-the-hard-way
kind: Config
preferences: {}
users:
- name: admin
  user:
    client-certificate: /root/kubernetes-the-hard-way/admin.crt
    client-key: /root/kubernetes-the-hard-way/admin.key

 

 

Pod 네트워크 라우팅 구성

node-0, node-1에 PodCIDR과 통신을 위한 OS커널에 라우팅 설정을 구성합니다.

구성하려는 네트워크 대역은 다음과 같습니다.

항목 네트워크 대역 or IP
clusterCIDR 10.200.0.0/16
→ node-0 PodCIDR 10.200.0.0/24
→ node-1 PodCIDR 10.200.1.0/24
ServiceCIDR 10.32.0.0/24
→ api clusterIP 10.32.0.1

 

# Print the internal IP address and Pod CIDR range for each worker instance:
root@jumpbox:~/kubernetes-the-hard-way# SERVER_IP=$(grep server machines.txt | cut -d " " -f 1)
NODE_0_IP=$(grep node-0 machines.txt | cut -d " " -f 1)
NODE_0_SUBNET=$(grep node-0 machines.txt | cut -d " " -f 4)
NODE_1_IP=$(grep node-1 machines.txt | cut -d " " -f 1)
NODE_1_SUBNET=$(grep node-1 machines.txt | cut -d " " -f 4)
echo $SERVER_IP $NODE_0_IP $NODE_0_SUBNET $NODE_1_IP $NODE_1_SUBNET
192.168.10.100 192.168.10.101 10.200.0.0/24 192.168.10.102 10.200.1.0/24

root@jumpbox:~/kubernetes-the-hard-way# ssh server ip -c route
default via 10.0.2.2 dev eth0
10.0.2.0/24 dev eth0 proto kernel scope link src 10.0.2.15
192.168.10.0/24 dev eth1 proto kernel scope link src 192.168.10.100

root@jumpbox:~/kubernetes-the-hard-way# ssh root@server <<EOF
  ip route add ${NODE_0_SUBNET} via ${NODE_0_IP}
  ip route add ${NODE_1_SUBNET} via ${NODE_1_IP}
EOF
Pseudo-terminal will not be allocated because stdin is not a terminal.
Linux server 6.1.0-40-arm64 #1 SMP Debian 6.1.153-1 (2025-09-20) aarch64

This system is built by the Bento project by Chef Software
More information can be found at https://github.com/chef/bento

Use of this system is acceptance of the OS vendor EULA and License Agreements.

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.

root@jumpbox:~/kubernetes-the-hard-way# ssh server ip -c route
default via 10.0.2.2 dev eth0
10.0.2.0/24 dev eth0 proto kernel scope link src 10.0.2.15
10.200.0.0/24 via 192.168.10.101 dev eth1
10.200.1.0/24 via 192.168.10.102 dev eth1
192.168.10.0/24 dev eth1 proto kernel scope link src 192.168.10.100

root@jumpbox:~/kubernetes-the-hard-way# ssh node-0 ip -c route
default via 10.0.2.2 dev eth0
10.0.2.0/24 dev eth0 proto kernel scope link src 10.0.2.15
192.168.10.0/24 dev eth1 proto kernel scope link src 192.168.10.101

root@jumpbox:~/kubernetes-the-hard-way# ssh root@node-0 <<EOF
  ip route add ${NODE_1_SUBNET} via ${NODE_1_IP}
EOF
Pseudo-terminal will not be allocated because stdin is not a terminal.
Linux node-0 6.1.0-40-arm64 #1 SMP Debian 6.1.153-1 (2025-09-20) aarch64

This system is built by the Bento project by Chef Software
More information can be found at https://github.com/chef/bento

Use of this system is acceptance of the OS vendor EULA and License Agreements.

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.

root@jumpbox:~/kubernetes-the-hard-way# ssh node-0 ip -c route
default via 10.0.2.2 dev eth0
10.0.2.0/24 dev eth0 proto kernel scope link src 10.0.2.15
10.200.1.0/24 via 192.168.10.102 dev eth1
192.168.10.0/24 dev eth1 proto kernel scope link src 192.168.10.101


root@jumpbox:~/kubernetes-the-hard-way# ssh node-1 ip -c route
default via 10.0.2.2 dev eth0
10.0.2.0/24 dev eth0 proto kernel scope link src 10.0.2.15
192.168.10.0/24 dev eth1 proto kernel scope link src 192.168.10.102

root@jumpbox:~/kubernetes-the-hard-way# ssh root@node-1 <<EOF
  ip route add ${NODE_0_SUBNET} via ${NODE_0_IP}
EOF
Pseudo-terminal will not be allocated because stdin is not a terminal.
Linux node-1 6.1.0-40-arm64 #1 SMP Debian 6.1.153-1 (2025-09-20) aarch64

This system is built by the Bento project by Chef Software
More information can be found at https://github.com/chef/bento

Use of this system is acceptance of the OS vendor EULA and License Agreements.

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.

root@jumpbox:~/kubernetes-the-hard-way# ssh node-1 ip -c route
default via 10.0.2.2 dev eth0
10.0.2.0/24 dev eth0 proto kernel scope link src 10.0.2.15
10.200.0.0/24 via 192.168.10.101 dev eth1
192.168.10.0/24 dev eth1 proto kernel scope link src 192.168.10.102

 

 

Smoke Test

최종 구성도는 포스팅 상단에 작성한 다음 그림과 같습니다. 

 

kubernetes 동작 테스트를 진행하겠습니다.

root@jumpbox:~/kubernetes-the-hard-way# kubectl create secret generic kubernetes-the-hard-way --from-literal="mykey=mydata"
secret/kubernetes-the-hard-way created

root@jumpbox:~/kubernetes-the-hard-way# kubectl get secret kubernetes-the-hard-way
NAME                      TYPE     DATA   AGE
kubernetes-the-hard-way   Opaque   1      5s

root@jumpbox:~/kubernetes-the-hard-way# kubectl get secret kubernetes-the-hard-way -o yaml
apiVersion: v1
data:
  mykey: bXlkYXRh
kind: Secret
metadata:
  creationTimestamp: "2026-01-11T00:33:42Z"
  name: kubernetes-the-hard-way
  namespace: default
  resourceVersion: "4565"
  uid: ce1640d0-b57d-4e66-9edd-168e2580710b
type: Opaque

root@jumpbox:~/kubernetes-the-hard-way# kubectl get secret kubernetes-the-hard-way -o jsonpath='{.data.mykey}' ; echo
bXlkYXRh

root@jumpbox:~/kubernetes-the-hard-way# kubectl get secret kubernetes-the-hard-way -o jsonpath='{.data.mykey}' | base64 -d ; echo
mydata

# Print a hexdump of the kubernetes-the-hard-way secret stored in etcd
## etcdctl get … : etcd 내부 key 직접 조회, kubernetes API 우회(매우 강력한 접근)
## Secret 리소스의 etcd 실제 저장 경로: /registry/<resource>/<namespace>/<name> -> /registry/secrets/default/kubernetes-the-hard-way
root@jumpbox:~/kubernetes-the-hard-way# ssh root@server \
    'etcdctl get /registry/secrets/default/kubernetes-the-hard-way | hexdump -C'
00000000  2f 72 65 67 69 73 74 72  79 2f 73 65 63 72 65 74  |/registry/secret|
00000010  73 2f 64 65 66 61 75 6c  74 2f 6b 75 62 65 72 6e  |s/default/kubern|
00000020  65 74 65 73 2d 74 68 65  2d 68 61 72 64 2d 77 61  |etes-the-hard-wa|
00000030  79 0a 6b 38 73 3a 65 6e  63 3a 61 65 73 63 62 63  |y.k8s:enc:aescbc|
00000040  3a 76 31 3a 6b 65 79 31  3a 8a 92 59 2e 76 12 be  |:v1:key1:..Y.v..|
00000050  c6 bf 8a 5e 14 50 fe d4  a8 0a 8c 02 95 bd 38 06  |...^.P........8.|
00000060  53 5d 71 8d 33 db 1b 35  3c 57 b3 ca 81 ca 52 ab  |S]q.3..5<W....R.|
00000070  d9 7b 5b c1 cf 1d 6a e9  26 be 67 b9 33 a6 ba 38  |.{[...j.&.g.3..8|
00000080  0a ad af d3 0e 1e d7 ad  59 54 4b 1e 93 28 12 80  |........YTK..(..|
00000090  67 55 44 dd 4a 00 9c c7  58 5a 10 6b 47 76 42 76  |gUD.J...XZ.kGvBv|
000000a0  64 5d da cc 11 7d f7 38  60 c7 d8 70 ac ea 75 49  |d]...}.8`..p..uI|
000000b0  fd d8 83 6a 5e bb 9f 8f  60 73 f5 9f 95 e6 05 00  |...j^...`s......|
000000c0  2e af a9 63 38 be a7 5a  7e e4 a2 23 52 fd 47 63  |...c8..Z~..#R.Gc|
000000d0  d1 12 41 3b 36 4d 7a ce  d7 0c 25 02 d8 40 d5 a7  |..A;6Mz...%..@..|
000000e0  04 ee 55 b1 20 5f e6 02  b6 ec a8 ab 7c fa 51 81  |..U. _......|.Q.|
000000f0  c3 78 18 64 f8 1a e0 3d  44 d9 57 3b 80 4d d5 35  |.x.d...=D.W;.M.5|
00000100  df 2f 79 c4 5c 1e 40 a5  93 ba 5f 52 bd f6 c2 fd  |./y.\.@..._R....|
00000110  03 c7 ff e0 59 68 c1 ec  6c 02 af 94 56 45 10 6d  |....Yh..l...VE.m|
00000120  d1 ce 21 d3 42 f8 12 e8  2e 77 46 8a fd 4f 99 29  |..!.B....wF..O.)|
00000130  a8 ba 9c 26 fe 55 cd 12  f7 29 2e 7d 0b ee 12 c6  |...&.U...).}....|
00000140  ad a2 60 83 56 b6 af 14  a4 13 20 1c ef 4e 95 19  |..`.V..... ..N..|
00000150  c1 b6 dd fc 78 40 66 82  07 0a                    |....x@f...|
0000015a

... # Kubernetes Secret이 etcd에 AES-CBC 방식으로 정상 암호화되어 저장되고 있음을 증명하는 출력
# k8s:enc	: Kubernetes 암호화 포맷
# aescbc	: 암호화 알고리즘 (AES-CBC)
# v1	    : encryption provider 버전
# key1	  : 사용된 encryption key 이름
# 이후 데이터는 암호화된 데이터

'스터디 > K8s Deploy' 카테고리의 다른 글

[K8s Deploy] Kubespray offline 설치  (0) 2026.02.15
[K8s Deploy] Kubespary HA & Upgrade  (0) 2026.02.04
[K8s] Kubespray 배포 분석  (0) 2026.02.01
[K8s Deploy] Kubeadm Deep Dive  (0) 2026.01.24
[K8s Deploy] Ansible 기초  (1) 2026.01.18