1. 개요
쿠버네티스 노드를 클러스터에 조인하는 과정에 대한 내용이다. kubeadm init 이후 워커 노드에서 kubeadm join을 실행하고, 마스터 노드에서 조인 여부를 확인한다.
2. 사전 정보
- 사전에 설치해야 할 내용은 /index.php/cloud/1315-kubeadm-toolkit을 참고한다.
- 쿠버네티스 클러스터는 하나의 마스터와 여러 노드(=worker, minion)로 이루어져 있다.
- 아래 예시에 나온
kubeadm join명령은 마스터 노드에서 kubeadminit을 실행했을 때 출력된 명령이다. 실제 환경에서는 토큰, 해시, API 서버 주소가 다르므로 본인 환경에서 출력된 값을 사용해야 한다.
3. 노드 조인
사전에 설치되어야 할 것이 모두 설치되었다면, 워커 노드에 접속해서 마스터에 조인한다.
# kubeadm join 10.0.10.220:6443 --token 09si41.rjipcw83obk3vna4 --discovery-token-ca-cert-hash sha256:fc629584400772a5f0b61f4579a317399b1b430793e28129206ed02ea1882134
[preflight] running pre-flight checks
[WARNING RequiredIPVSKernelModulesAvailable]: the IPVS proxier will not be used, because the following required kernel modules are not loaded: [ip_vs ip_vs_rr ip_vs_wrr ip_vs_sh] or no builtin kernel ipvs support: map[ip_vs:{} ip_vs_rr:{} ip_vs_wrr:{} ip_vs_sh:{} nf_conntrack_ipv4:{}]
you can solve this problem with following methods:
1. Run 'modprobe -- ' to load missing kernel modules;
2. Provide the missing builtin kernel ipvs support
I0807 04:27:53.370349 14840 kernel_validator.go:81] Validating kernel version
I0807 04:27:53.370517 14840 kernel_validator.go:96] Validating kernel config
[discovery] Trying to connect to API Server "10.0.10.220:6443"
[discovery] Created cluster-info discovery client, requesting info from "https://10.0.10.220:6443"
실패했다. 결론적으로는 /etc/hosts에 호스트 자신에 대한 정보가 없었다. 해당 내용을 추가하고 다시 실행한다. 이때 IPVS 관련 경고는 현재 환경에서 IPVS 커널 모듈이 로드되지 않았다는 의미이며, 이 글의 조인 실패 원인은 별도로 호스트 이름 해석 문제였다.
# kubeadm join 10.0.10.220:6443 --token 09si41.rjipcw83obk3vna4 --discovery-token-ca-cert-hash sha256:fc629584400772a5f0b61f4579a317399b1b430793e28129206ed02ea1882134
[preflight] running pre-flight checks
[WARNING RequiredIPVSKernelModulesAvailable]: the IPVS proxier will not be used, because the following required kernel modules are not loaded: [ip_vs ip_vs_rr ip_vs_wrr ip_vs_sh] or no builtin kernel ipvs support: map[ip_vs:{} ip_vs_rr:{} ip_vs_wrr:{} ip_vs_sh:{} nf_conntrack_ipv4:{}]
you can solve this problem with following methods:
1. Run 'modprobe -- ' to load missing kernel modules;
2. Provide the missing builtin kernel ipvs support
I0807 04:27:53.370349 14840 kernel_validator.go:81] Validating kernel version
I0807 04:27:53.370517 14840 kernel_validator.go:96] Validating kernel config
[discovery] Trying to connect to API Server "10.0.10.220:6443"
[discovery] Created cluster-info discovery client, requesting info from "https://10.0.10.220:6443"
이번에는 이 상태로 계속 멈춰 있었다. 결론적으로는 Security Group에서 6443 포트가 막혀 있었기 때문이다. 6443 포트를 열고 다시 실행한다. 6443은 kube-apiserver가 사용하는 포트이므로, 워커 노드에서 마스터 노드의 해당 포트로 접근할 수 있어야 한다.
# kubeadm join 10.0.10.220:6443 --token 09si41.rjipcw83obk3vna4 --discovery-token-ca-cert-hash sha256:fc629584400772a5f0b61f4579a317399b1b430793e28129206ed02ea1882134
[preflight] running pre-flight checks
[WARNING RequiredIPVSKernelModulesAvailable]: the IPVS proxier will not be used, because the following required kernel modules are not loaded: [ip_vs_wrr ip_vs_sh ip_vs ip_vs_rr] or no builtin kernel ipvs support: map[ip_vs_rr:{} ip_vs_wrr:{} ip_vs_sh:{} nf_conntrack_ipv4:{} ip_vs:{}]
you can solve this problem with following methods:
1. Run 'modprobe -- ' to load missing kernel modules;
2. Provide the missing builtin kernel ipvs support
I0807 04:28:53.156400 14915 kernel_validator.go:81] Validating kernel version
I0807 04:28:53.156614 14915 kernel_validator.go:96] Validating kernel config
[discovery] Trying to connect to API Server "10.0.10.220:6443"
[discovery] Created cluster-info discovery client, requesting info from "https://10.0.10.220:6443"
[discovery] Requesting info from "https://10.0.10.220:6443" again to validate TLS against the pinned public key
[discovery] Cluster info signature and contents are valid and TLS certificate validates against pinned roots, will use API Server "10.0.10.220:6443"
[discovery] Successfully established connection with API Server "10.0.10.220:6443"
[kubelet] Downloading configuration for the kubelet from the "kubelet-config-1.11" ConfigMap in the kube-system namespace
[kubelet] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[preflight] Activating the kubelet service
[tlsbootstrap] Waiting for the kubelet to perform the TLS Bootstrap...
[patchnode] Uploading the CRI Socket information "/var/run/dockershim.sock" to the Node API object "ip-10-0-10-196" as an annotation
This node has joined the cluster:
* Certificate signing request was sent to master and a response
was received.
* The Kubelet was informed of the new secure connection details.
Run 'kubectl get nodes' on the master to see this node join the cluster.
4. 마스터 노드에서 확인
4-1. 연결되기 전
$ kubectl get nodes NAME STATUS ROLES AGE VERSION ip-10-0-10-220 NotReady master 1h v1.11.1
4-2. 연결된 후
$ kubectl get nodes NAME STATUS ROLES AGE VERSION ip-10-0-10-196 NotReady 45s v1.11.1 ip-10-0-10-220 NotReady master 2h v1.11.1
노드가 목록에 추가된 것을 확인할 수 있다. 참고로 아직 NotReady 상태인 이유는 CNI(Container Network Interface)가 배포되지 않았기 때문이다.
5. CNI 배포
그러면 CNI를 배포한다. 여기서는 Calico 기준이다.
$ kubectl apply -f https://docs.projectcalico.org/v2.6/getting-started/kubernetes/installation/hosted/kubeadm/1.6/calico.yaml configmap/calico-config created daemonset.extensions/calico-etcd created service/calico-etcd created daemonset.extensions/calico-node created deployment.extensions/calico-kube-controllers created deployment.extensions/calico-policy-controller created clusterrolebinding.rbac.authorization.k8s.io/calico-cni-plugin created clusterrole.rbac.authorization.k8s.io/calico-cni-plugin created serviceaccount/calico-cni-plugin created clusterrolebinding.rbac.authorization.k8s.io/calico-kube-controllers created clusterrole.rbac.authorization.k8s.io/calico-kube-controllers created serviceaccount/calico-kube-controllers created
노드 상태를 확인한다.
$ kubectl get nodes NAME STATUS ROLES AGE VERSION ip-10-0-10-196 NotReady 48m v1.11.1 ip-10-0-10-220 NotReady master 2h v1.11.1
아직 NotReady 상태에 머물러 있다. systemctl restart kubelet로 kubelet을 재기동한 후 다시 상태를 확인한다.
$ kubectl get nodes NAME STATUS ROLES AGE VERSION ip-10-0-10-196 Ready 49m v1.11.1 ip-10-0-10-220 NotReady master 2h v1.11.1
워커 노드가 Ready로 올라왔다. 그리고 조금 더 기다리면 마스터도 Ready로 올라온다.
$ kubectl get nodes NAME STATUS ROLES AGE VERSION ip-10-0-10-196 Ready 51m v1.11.1 ip-10-0-10-220 Ready master 3h v1.11.1
확실치 않은 부분: CNI 배포 후 kubelet restart를 꼭 해줘야 하는지, 아니면 기다리면 자동으로 마스터가 Ready가 되는지 여부는 더 확인이 필요하다. 같은 상황을 점검할 때는 kubectl get pods -n kube-system으로 CNI 관련 파드가 정상적으로 올라오는지 함께 확인하면 원인 파악에 도움이 된다.