지난 포스팅에서 기본적인 Docker 와 Docker-Compose 의 설치가 끝났습니다.

이번시간에는 Kubernetes 를 설치해 보도록 하겠습니다.




Kubernetes 설치하기


이제 Kubernetes 를 이용해서, 효율적인 Docker, Cluster 관리를 할 수 있도록 설치를 해 보겠습니다.




Kubernetes 설치




Kubernetes 가 무엇인지는 다른 글들을 참고하시기 바랍니다.

개인적으로 반드시 Kubernetes 의 Architecture 에 대한 글을 보시길 권장합니다. 나중에 Kubernetes 를 사용하려면, 여러가지 개념과 오브젝트들이 등장하는데, Artchitecture 를 모르면 절대 이해할 수가 없습니다.




Kubernetes 에는 Master Node 와 Worker Node 가 있습니다.

아래는 Master 와 Worker 환경 모두에서 설치해야 하는 공통 내용입니다.





Master / Worker Node 공통된 설치내용




Kubernetes 를 설치하고 세팅하는 것이 복잡하다보니, 다양한 설치 솔류션이 있습니다.

AWS, Google Cloud 등에서 설치하기 위한 솔루션도 따로 마련되어 있습니다.


Kubernetes 설치 솔루션 목록:

https://kubernetes.io/docs/setup/pick-right-solution/



저는 독립된 Cloud 환경에서 설치하려고 합니다.

Kubeadm (Kubernetes Admin)이라는 녀석을 통해서 설치할 것입니다.



Kubeadm 을 이용한 Kubernetes 설치 공식 매뉴얼:

https://kubernetes.io/docs/setup/independent/create-cluster-kubeadm/



사용하는 포트목록 참고:

https://kubernetes.io/docs/setup/independent/install-kubeadm/




먼저 Docker 를 모든 Node 에 설치해 줍니다.

이전 포스팅을 참고하세요.



여기서부터는 설치과정에서 번거로우니 먼저 root 권한으로 쉘을 실행한 후, 진행합니다.


$ sudo -i

#



Repository 를 설정하고, SELinux 를 끕니다.

그리고 위의 세가지를 설치합니다.


cat <<EOF > /etc/yum.repos.d/kubernetes.repo

[kubernetes]

name=Kubernetes

baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64

enabled=1

gpgcheck=1

repo_gpgcheck=1

gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg

exclude=kube*

EOF

# setenforce 0

# yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes

# systemctl enable kubelet && systemctl start kubelet



설치가 끝나고나면 아래처럼 네트워크 설정을 변경해 줍니다.


# echo 1 > /proc/sys/net/ipv4/ip_forward



그리고 swap 도 off 시켜주어야 합니다.


# swapoff -a



시스템 설정도 아래처럼 해 줍니다.


cat <<EOF >  /etc/sysctl.d/k8s.conf

net.bridge.bridge-nf-call-ip6tables = 1

net.bridge.bridge-nf-call-iptables = 1

EOF

# sysctl --system



마지막으로 서비스에 등록하고 실행해 줍니다.

systemctl daemon-reload

# systemctl restart kubelet

# systemctl enable kubelet








Master 에서 설치할 것들




이제 Master 에서 추가적인 설치/설정을 해 주면 됩니다.

다일 Master 클러스터를 구성하도록 하겠습니다.


공식 설치방법 주소:

https://kubernetes.io/docs/setup/independent/create-cluster-kubeadm/



Kubernetes 의 Master Node 에 pod network 애드온을 설치해 주어야 합니다.

여러가지 애드온이 있는데, 아래에서 각 장단점을 읽어보고 원하는것 하나를 설치하면 됩니다.


https://kubernetes.io/docs/setup/independent/create-cluster-kubeadm/#pod-network


먼저 다시한번 ip_forward 규칙을 1로 세팅해 줍니다. (버그인지 모르겠으나, 다시 설정해야 함)

echo 1 > /proc/sys/net/ipv4/ip_forward


개인적으로 처음에 Kube-router 를 설치하려고 했으나,,

수많은 삽질을 하게 되었고, 그 결과 Flannel 을 설치하였습니다. =_=

Flannel 을 사용할 경우, kubeadm 을 초기화는 다음과 같습니다.


# kubeadm init --pod-network-cidr=10.244.0.0/16


뒤쪽에 있는 --pod-network-cidr=10.244.0.0/16 은 Flannel 에서 사용하는 플래그입니다.
(만약 이미 유사한 대역의 사설IP에 위치해 있다면, 192.168.1.0/24 식으로 바꿔도 됩니다.)
잠시 기다리면, 아래와 같이 초기화가 끝이 납니다.

# kubeadm init --pod-network-cidr 10.244.0.0/16

[init] using Kubernetes version: v1.11.2

[preflight] running pre-flight checks

I0903 19:18:37.032588   86064 kernel_validator.go:81] Validating kernel version

I0903 19:18:37.032757   86064 kernel_validator.go:96] Validating kernel config

[preflight/images] Pulling images required for setting up a Kubernetes cluster

[preflight/images] This might take a minute or two, depending on the speed of yo                                           ur internet connection

[preflight/images] You can also perform this action in beforehand using 'kubeadm                                            config images pull'

[kubelet] Writing kubelet environment file with flags to file "/var/lib/kubelet/                                           kubeadm-flags.env"

[kubelet] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"

[preflight] Activating the kubelet service

[certificates] Generated ca certificate and key.

[certificates] Generated apiserver certificate and key.

[certificates] apiserver serving cert is signed for DNS names [test-k8s-master-n                                           cl kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.c                                           luster.local] and IPs [10.96.0.1 10.106.234.130]

[certificates] Generated apiserver-kubelet-client certificate and key.

[certificates] Generated sa key and public key.

[certificates] Generated front-proxy-ca certificate and key.

[certificates] Generated front-proxy-client certificate and key.

[certificates] Generated etcd/ca certificate and key.

[certificates] Generated etcd/server certificate and key.

[certificates] etcd/server serving cert is signed for DNS names [test-k8s-master                                           -ncl localhost] and IPs [127.0.0.1 ::1]

[certificates] Generated etcd/peer certificate and key.

[certificates] etcd/peer serving cert is signed for DNS names [test-k8s-master-n                                           cl localhost] and IPs [10.106.234.130 127.0.0.1 ::1]

[certificates] Generated etcd/healthcheck-client certificate and key.

[certificates] Generated apiserver-etcd-client certificate and key.

[certificates] valid certificates and keys now exist in "/etc/kubernetes/pki"

[kubeconfig] Wrote KubeConfig file to disk: "/etc/kubernetes/admin.conf"

[kubeconfig] Wrote KubeConfig file to disk: "/etc/kubernetes/kubelet.conf"

[kubeconfig] Wrote KubeConfig file to disk: "/etc/kubernetes/controller-manager.                                           conf"

[kubeconfig] Wrote KubeConfig file to disk: "/etc/kubernetes/scheduler.conf"

[controlplane] wrote Static Pod manifest for component kube-apiserver to "/etc/k                                           ubernetes/manifests/kube-apiserver.yaml"

[controlplane] wrote Static Pod manifest for component kube-controller-manager t                                           o "/etc/kubernetes/manifests/kube-controller-manager.yaml"

[controlplane] wrote Static Pod manifest for component kube-scheduler to "/etc/k                                           ubernetes/manifests/kube-scheduler.yaml"

[etcd] Wrote Static Pod manifest for a local etcd instance to "/etc/kubernetes/m                                           anifests/etcd.yaml"

[init] waiting for the kubelet to boot up the control plane as Static Pods from                                            directory "/etc/kubernetes/manifests"

[init] this might take a minute or longer if the control plane images have to be                                            pulled

[apiclient] All control plane components are healthy after 40.501916 seconds

[uploadconfig] storing the configuration used in ConfigMap "kubeadm-config" in t                                           he "kube-system" Namespace

[kubelet] Creating a ConfigMap "kubelet-config-1.11" in namespace kube-system wi                                           th the configuration for the kubelets in the cluster

[markmaster] Marking the node test-k8s-master-ncl as master by adding the label                                            "node-role.kubernetes.io/master=''"

[markmaster] Marking the node test-k8s-master-ncl as master by adding the taints                                            [node-role.kubernetes.io/master:NoSchedule]

[patchnode] Uploading the CRI Socket information "/var/run/dockershim.sock" to t                                           he Node API object "test-k8s-master-ncl" as an annotation

[bootstraptoken] using token: pvpoff.3gi89fsxl6q6vq21

[bootstraptoken] configured RBAC rules to allow Node Bootstrap tokens to post CS                                           Rs in order for nodes to get long term certificate credentials

[bootstraptoken] configured RBAC rules to allow the csrapprover controller autom                                           atically approve CSRs from a Node Bootstrap Token

[bootstraptoken] configured RBAC rules to allow certificate rotation for all nod                                           e client certificates in the cluster

[bootstraptoken] creating the "cluster-info" ConfigMap in the "kube-public" name                                           space

[addons] Applied essential addon: CoreDNS

[addons] Applied essential addon: kube-proxy


Your Kubernetes master has initialized successfully!


To start using your cluster, you need to run the following as a regular user:


  mkdir -p $HOME/.kube

  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config

  sudo chown $(id -u):$(id -g) $HOME/.kube/config


You should now deploy a pod network to the cluster.

Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:

  https://kubernetes.io/docs/concepts/cluster-administration/addons/


You can now join any number of machines by running the following on each node

as root:


  kubeadm join 10.106.234.130:6443 --token pvpoff.3gi19fsxl8q6vq47 --discovery-t                                           oken-ca-cert-hash sha256:e57e547d3697386005324524878f42b670db3f83227ff247464f470                                           f2fddf2d6



위 출력에서 중요한 것은 3가지입니다.
(제가 파란색으로 표시한 부분)


설치가 완료되었다면, kubernetes 의 admin 설정을 현재 사용자의 홈에 저장합니다.

일반 사용자를 위해서는, root 에서 빠져 나온 뒤에, 파일을 옮깁니다.


# exit

mkdir -p $HOME/.kube

sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config

sudo chown $(id -u):$(id -g) $HOME/.kube/config



root 에서 실행할 것이면, 아래처럼 환경변수에 등록해 줍니다.


# export KUBECONFIG=/etc/kubernetes/admin.conf




이제 앞서 설치하려고 했던 Flannel 을 설치합니다.


# kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/v0.10.0/Documentation/kube-flannel.yml


clusterrole.rbac.authorization.k8s.io/flannel created

clusterrolebinding.rbac.authorization.k8s.io/flannel created

serviceaccount/flannel created

configmap/kube-flannel-cfg created

daemonset.extensions/kube-flannel-ds created



!! 현재 flannel 최신 yml 파일은 다음과 같습니다. 설치시 반드시 최신 버전 확인 바랍니다.

kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/bc79dd1505b0c8681ece4de4c0d86c5cd2643275/Documentation/kube-flannel.yml









Master 에서 설치 확인




마스터에서 설정이 끝나고나면, 아래처럼 설치된 pods 확인합니다.


# kubectl get pods --all-namespaces

NAMESPACE     NAME                                          READY     STATUS    RESTARTS   AGE

kube-system   coredns-78fcdf6894-c6x7x                      1/1       Running   0          12m

kube-system   coredns-78fcdf6894-qf66q                      1/1       Running   0          12m

kube-system   etcd-test-k8s-master-ncl                      1/1       Running   0          1m

kube-system   kube-apiserver-test-k8s-master-ncl            1/1       Running   0          1m

kube-system   kube-controller-manager-test-k8s-master-ncl   1/1       Running   0          1m

kube-system   kube-flannel-ds-fblsn                         1/1       Running   0          1m

kube-system   kube-proxy-2grf9                              1/1       Running   0          7m

kube-system   kube-scheduler-test-k8s-master-ncl            1/1       Running   0          1m




Pod 의 Status 가 모두 Running 이면 제대로 설치된 것입니다.






CoreDns 의 오류 문제해결



만약에 coredns 의 상태가 아래처럼 Running 이 아닌 경우라면,

NAMESPACE     NAME                                         READY   STATUS             RESTARTS   AGE

kube-system   coredns-576cbf47c7-6vnqn                     0/1     CrashLoopBackOff   9          15m

kube-system   coredns-576cbf47c7-qp6k2                     0/1     CrashLoopBackOff   9          15m



다음과 같이 해결 할 수 있습니다.

kubectl -n kube-system get deployment coredns -o yaml | \

sed 's/allowPrivilegeEscalation: false/allowPrivilegeEscalation: true/g' | \

kubectl apply -f -







Worker Node 를 Master Node 에 등록




이제 각 Worker Node 를 Master Node 에 등록해 주어야 합니다.

(Cluster 에 등록)


앞서 Master 를 초기화 한 결과로, 마지막 부분에 worker node 에서 실행해야 할 명령어가 출력되었었습니다.

출력되었던 것을 그대로 복사해서 모든 Worker Node 에서 실행해 줍니다.


$ sudo kubeadm join 10.106.234.130:6443 --token pvpoff.3gi19fsxl8q6vq47 --discovery-token-ca-cert-hash sha256:e57e547d3697386005324524878f42b670db3f83227ff247464f4702fddf2d6



모든 Worker Node 를 등록하고나면, 아래처럼 Master Node 에서 Worker Node 가 등록된것을 확인 할 수 있습니다.

저의 경우 3개를 등록하였습니다.


kubectl get nodes

NAME                    STATUS    ROLES     AGE       VERSION

k8s-master-ncl     Ready     master    19m       v1.11.2

kube-node001-ncl   Ready     <none>    1m        v1.11.2

kube-node002-ncl   Ready     <none>    1m        v1.11.2

kube-node003-ncl   Ready     <none>    1m        v1.11.2




만약 Token 과 CA Hash 값을 잃어버렸다면, 다음과 같이 찾아낼 수 있습니다.
토큰은 아래처럼 찾을 수 있고, 없다면 새로 생성하면 됩니다.

토큰 목록 보기

kubeadm token list


토큰 생성하기

kubeadm token create


CA 인증서 Hash 값

openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | \

openssl dgst -sha256 -hex | sed 's/^.* //'



그리고 결과값을 아래처럼 조합하면 됩니다.

kubeadm join [API_SERVER_ADDR]:[API_SERVER_PORT] --token [TOKEN] --discovery-token-ca-cert-hash sha256:[CA_HASH]