Add files via upload
437
KUBE_VERSION_UPGRADE_README.md
Normal file
@@ -0,0 +1,437 @@
|
||||
# kubeadm 클러스터 업그레이드 가이드
|
||||
|
||||
## 구성 요소 및 버전
|
||||
* kubeadm, kubelet, kubectl
|
||||
|
||||
## Prerequisites
|
||||
* upgrade 할 kubeadm version 선택
|
||||
```bash
|
||||
yum list --showduplicates kubeadm --disableexcludes=kubernetes
|
||||
```
|
||||
* 하나의 MINOR 버전에서 다음 MINOR 버전으로, 또는 동일한 MINOR의 PATCH 버전 사이에서만 업그레이드할 수 있다.
|
||||
* 즉, 업그레이드할 때 MINOR 버전을 건너 뛸 수 없다. 예를 들어, 1.y에서 1.y+1로 업그레이드할 수 있지만, 1.y에서 1.y+2로 업그레이드할 수는 없다.
|
||||
* ex) 1.15 버전에서 1.17 버전으로 한번에 업그레이드는 불가능 하다. 1.15 -> 1.16 -> 1.17 스텝을 진행 해야 한다.
|
||||
* runtime으로 crio 사용시, CRI-O 메이저와 마이너 버전은 쿠버네티스 메이저와 마이너 버전이 일치해야 한다. 따라서 업데이트한 쿠버네티스 버전에 따라 crio 버전도 함께 업데이트 한다.
|
||||
|
||||
## 폐쇄망 가이드
|
||||
1. **폐쇄망에서 설치하는 경우** 아래 가이드를 참고 하여 image registry를 먼저 구축한다.
|
||||
* https://github.com/tmax-cloud/hypercloud-install-guide/tree/master/Image_Registry
|
||||
2. 사용하는 image repository에 k8s 설치 시 필요한 이미지를 push한다.
|
||||
* 작업 디렉토리 생성 및 환경 설정
|
||||
```bash
|
||||
$ mkdir -p ~/k8s-install
|
||||
$ cd ~/k8s-install
|
||||
```
|
||||
* 외부 네트워크 통신이 가능한 환경에서 필요한 이미지를 다운받는다. (1.15.x -> 1.17.x으로 upgrade 하는 경우 두 버전의 image들이 모두 필요하다)
|
||||
* v1.16.15 images
|
||||
```bash
|
||||
$ sudo docker pull k8s.gcr.io/kube-proxy:v1.16.15
|
||||
$ sudo docker pull k8s.gcr.io/kube-apiserver:v1.16.15
|
||||
$ sudo docker pull k8s.gcr.io/kube-controller-manager:v1.16.15
|
||||
$ sudo docker pull k8s.gcr.io/kube-scheduler:v1.16.15
|
||||
$ sudo docker pull k8s.gcr.io/etcd:3.3.15-0
|
||||
$ sudo docker pull k8s.gcr.io/coredns:1.6.2
|
||||
$ sudo docker pull k8s.gcr.io/pause:3.1
|
||||
```
|
||||
* v1.17.6 images
|
||||
```bash
|
||||
$ sudo docker pull k8s.gcr.io/kube-proxy:v1.17.6
|
||||
$ sudo docker pull k8s.gcr.io/kube-apiserver:v1.17.6
|
||||
$ sudo docker pull k8s.gcr.io/kube-controller-manager:v1.17.6
|
||||
$ sudo docker pull k8s.gcr.io/kube-scheduler:v1.17.6
|
||||
$ sudo docker pull k8s.gcr.io/etcd:3.4.3-0
|
||||
$ sudo docker pull k8s.gcr.io/coredns:1.6.5
|
||||
$ sudo docker pull k8s.gcr.io/pause:3.1
|
||||
```
|
||||
|
||||
* docker image를 tar로 저장한다.
|
||||
* v1.16.15 images
|
||||
```bash
|
||||
$ sudo docker save -o kube-proxy-1.16.tar k8s.gcr.io/kube-proxy:v1.16.15
|
||||
$ sudo docker save -o kube-controller-manager-1.16.tar k8s.gcr.io/kube-apiserver:v1.16.15
|
||||
$ sudo docker save -o etcd-1.16.tar k8s.gcr.io/etcd:3.3.15-0
|
||||
$ sudo docker save -o coredns-1.16.tar k8s.gcr.io/coredns:1.6.2
|
||||
$ sudo docker save -o kube-scheduler-1.16.tar k8s.gcr.io/kube-scheduler:v1.16.15
|
||||
$ sudo docker save -o kube-apiserver-1.16.tar k8s.gcr.io/kube-apiserver:v1.16.15
|
||||
$ sudo docker save -o pause-1.16.tar k8s.gcr.io/pause:3.1
|
||||
```
|
||||
* v1.17.6 images
|
||||
```bash
|
||||
$ sudo docker save -o kube-proxy-1.17.tar k8s.gcr.io/kube-proxy:v1.17.6
|
||||
$ sudo docker save -o kube-controller-manager-1.17.tar k8s.gcr.io/kube-controller-manager:v1.17.6
|
||||
$ sudo docker save -o etcd-1.17.tar k8s.gcr.io/etcd:3.4.3-0
|
||||
$ sudo docker save -o coredns-1.17.tar k8s.gcr.io/coredns:1.6.5
|
||||
$ sudo docker save -o kube-scheduler-1.17.tar k8s.gcr.io/kube-scheduler:v1.17.6
|
||||
$ sudo docker save -o kube-apiserver-1.17.tar k8s.gcr.io/kube-apiserver:v1.17.6
|
||||
$ sudo docker save -o pause-1.17.tar k8s.gcr.io/pause:3.1
|
||||
```
|
||||
3. 위의 과정에서 생성한 tar 파일들을 폐쇄망 환경으로 이동시킨 뒤 사용하려는 registry에 이미지를 push한다.
|
||||
* v1.16.15 images
|
||||
```bash
|
||||
$ sudo docker load -i kube-apiserver-1.16.tar
|
||||
$ sudo docker load -i kube-scheduler-1.16.tar
|
||||
$ sudo docker load -i kube-controller-manager-1.16.tar
|
||||
$ sudo docker load -i kube-proxy-1.16.tar
|
||||
$ sudo docker load -i etcd-1.16.tar
|
||||
$ sudo docker load -i coredns-1.16.tar
|
||||
$ sudo docker load -i pause-1.16.tar
|
||||
```
|
||||
```bash
|
||||
$ sudo docker tag k8s.gcr.io/kube-apiserver:v1.16.15 ${REGISTRY}/k8s.gcr.io/kube-apiserver:v1.16.15
|
||||
$ sudo docker tag k8s.gcr.io/kube-proxy:v1.16.15 ${REGISTRY}/k8s.gcr.io/kube-proxy:v1.16.15
|
||||
$ sudo docker tag k8s.gcr.io/kube-controller-manager:v1.16.15 ${REGISTRY}/k8s.gcr.io/kube-controller-manager:v1.16.15
|
||||
$ sudo docker tag k8s.gcr.io/etcd:3.3.15-0 ${REGISTRY}/k8s.gcr.io/etcd:3.3.15-0
|
||||
$ sudo docker tag k8s.gcr.io/coredns:1.6.2 ${REGISTRY}/k8s.gcr.io/coredns:1.6.2
|
||||
$ sudo docker tag k8s.gcr.io/kube-scheduler:v1.16.15 ${REGISTRY}/k8s.gcr.io/kube-scheduler:v1.16.15
|
||||
$ sudo docker tag k8s.gcr.io/pause:3.1 ${REGISTRY}/k8s.gcr.io/pause:3.1
|
||||
```
|
||||
```bash
|
||||
$ sudo docker push ${REGISTRY}/k8s.gcr.io/kube-apiserver:v1.16.15
|
||||
$ sudo docker push ${REGISTRY}/k8s.gcr.io/kube-proxy:v1.16.15
|
||||
$ sudo docker push ${REGISTRY}/k8s.gcr.io/kube-controller-manager:v1.16.15
|
||||
$ sudo docker push ${REGISTRY}/k8s.gcr.io/etcd:3.3.15-0
|
||||
$ sudo docker push ${REGISTRY}/k8s.gcr.io/coredns:1.6.2
|
||||
$ sudo docker push ${REGISTRY}/k8s.gcr.io/kube-scheduler:v1.16.15
|
||||
$ sudo docker push ${REGISTRY}/k8s.gcr.io/pause:3.1
|
||||
```
|
||||
* v1.17.6 images
|
||||
```bash
|
||||
$ sudo docker load -i kube-apiserver-1.17.tar
|
||||
$ sudo docker load -i kube-scheduler-1.17.tar
|
||||
$ sudo docker load -i kube-controller-manager-1.17.tar
|
||||
$ sudo docker load -i kube-proxy-1.17.tar
|
||||
$ sudo docker load -i etcd-1.17.tar
|
||||
$ sudo docker load -i coredns-1.17.tar
|
||||
$ sudo docker load -i pause-1.17.tar
|
||||
```
|
||||
```bash
|
||||
$ sudo docker tag k8s.gcr.io/kube-apiserver:v1.17.6 ${REGISTRY}/k8s.gcr.io/kube-apiserver:v1.17.6
|
||||
$ sudo docker tag k8s.gcr.io/kube-proxy:v1.17.6 ${REGISTRY}/k8s.gcr.io/kube-proxy:v1.17.6
|
||||
$ sudo docker tag k8s.gcr.io/kube-controller-manager:v1.17.6 ${REGISTRY}/k8s.gcr.io/kube-controller-manager:v1.17.6
|
||||
$ sudo docker tag k8s.gcr.io/etcd:3.4.3-0 ${REGISTRY}/k8s.gcr.io/etcd:3.4.3-0
|
||||
$ sudo docker tag k8s.gcr.io/coredns:1.6.5 ${REGISTRY}/k8s.gcr.io/coredns:1.6.5
|
||||
$ sudo docker tag k8s.gcr.io/kube-scheduler:v1.17.6 ${REGISTRY}/k8s.gcr.io/kube-scheduler:v1.17.6
|
||||
$ sudo docker tag k8s.gcr.io/pause:3.1 ${REGISTRY}/k8s.gcr.io/pause:3.1
|
||||
```
|
||||
```bash
|
||||
$ sudo docker push ${REGISTRY}/k8s.gcr.io/kube-apiserver:v1.17.6
|
||||
$ sudo docker push ${REGISTRY}/k8s.gcr.io/kube-proxy:v1.17.6
|
||||
$ sudo docker push ${REGISTRY}/k8s.gcr.io/kube-controller-manager:v1.17.6
|
||||
$ sudo docker push ${REGISTRY}/k8s.gcr.io/etcd:3.4.3-0
|
||||
$ sudo docker push ${REGISTRY}/k8s.gcr.io/coredns:1.6.5
|
||||
$ sudo docker push ${REGISTRY}/k8s.gcr.io/kube-scheduler:v1.17.6
|
||||
$ sudo docker push ${REGISTRY}/k8s.gcr.io/pause:3.1
|
||||
```
|
||||
|
||||
## Steps
|
||||
0. [master upgrade](https://github.com/tmax-cloud/hypercloud-install-guide/blob/master/K8S_Master/KUBE_VERSION_UPGRADE_README.md#step0-kubernetes-master-upgrade)
|
||||
1. [node upgrade](https://github.com/tmax-cloud/hypercloud-install-guide/blob/master/K8S_Master/KUBE_VERSION_UPGRADE_README.md#step1-kubernetes-node-upgrade)
|
||||
|
||||
## Step0. kubernetes master upgrade
|
||||
* master에서 kubeadm을 upgrade 한다.
|
||||
```bash
|
||||
yum install -y kubeadm-설치버전 --disableexcludes=kubernetes
|
||||
|
||||
ex) yum install -y kubeadm-1.16.0-0 --disableexcludes=kubernetes
|
||||
|
||||
ex) yum install -y kubeadm-1.17.6-0 --disableexcludes=kubernetes
|
||||
```
|
||||
* 버전 확인
|
||||
```bash
|
||||
kubeadm version
|
||||
```
|
||||
* node drain
|
||||
* node drain 전 체크 사항
|
||||
* PDB가 존재하는 Pod가 drain하려는 node에 생성되어있는 경우 evict가 제한 되기 때문에, 아래 명령어로 drain이 가능한 상태인지 확인한다.
|
||||
```bash
|
||||
kubectl get pdb -A
|
||||
or
|
||||
kubectl get pdb <pdb-name> -oyaml
|
||||
```
|
||||
* ALLOWED DISRUPTIONS 및 drain 시키려는 node의 pod 상태를 확인한다.
|
||||
* PDB의 ALLOWED DISRUPTIONS가 drain을 시도하는 node에 뜬 pod(pdb 설정 pod) 개수보다 적을 경우 아래와 같이 다른 노드로 재스케줄링이 필요하다.
|
||||
* ex) virt-api pod가 drain하려는 node에 2개 떠있는데, ALLOWED DISRUPTIONS는 0 또는 1일 경우
|
||||
* 해당 조건에 만족하지 않는 경우 'Cannot evict pod as it would violate the pod's disruption budget' 와 같은 에러가 발생할 수 있다.
|
||||
* 해결 방법
|
||||
* 1) 해당 Pod를 다른 Node로 재스케줄링을 시도한다.
|
||||
```bash
|
||||
kubectl delete pod <pod-name>
|
||||
```
|
||||
* 2) 다른 Node의 리소스 부족, noScheduling 설정 등으로 인해 a번 재스케줄링이 불가할 경우엔 PDB 데이터를 삭제하고 drain한 후에 PDB 데이터를 복구한다.
|
||||
```bash
|
||||
kubectl get pdb <pdb-name> -o yaml > pdb-backup.yaml
|
||||
kubectl drain <node-to-drain> --ignore-daemonsets --delete-local-data
|
||||
kubectl apply -f pdb-backup.yaml
|
||||
```
|
||||
* node drain 실행
|
||||
* warning: node drain시 해당 node상의 pod가 evict되기 때문에, pod의 local-data의 경우 보존되지 않음
|
||||
```bash
|
||||
kubectl drain <node-to-drain> --ignore-daemonsets --delete-local-data
|
||||
|
||||
ex) kubectl drain k8s-master --ignore-daemonsets --delete-local-data
|
||||
```
|
||||
* 업그레이드 plan 변경
|
||||
```bash
|
||||
sudo kubeadm upgrade plan
|
||||
```
|
||||
* 업그레이드 시 kubeadm config 변경이 필요할 경우
|
||||
```bash
|
||||
sudo kubeadm upgrade plan --config=kubeadm_config.yaml
|
||||
```
|
||||
```bash
|
||||
[upgrade/config] Making sure the configuration is correct:
|
||||
[upgrade/config] Reading configuration from the cluster...
|
||||
[upgrade/config] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -oyaml'
|
||||
[preflight] Running pre-flight checks.
|
||||
[upgrade] Running cluster health checks
|
||||
[upgrade] Fetching available versions to upgrade to
|
||||
[upgrade/versions] Cluster version: v1.15.3
|
||||
[upgrade/versions] kubeadm version: v1.16.0
|
||||
[upgrade/versions] Latest stable version: v1.16.0
|
||||
[upgrade/versions] Latest version in the v1.15 series: v1.16.0
|
||||
|
||||
Components that must be upgraded manually after you have upgraded the control plane with 'kubeadm upgrade apply':
|
||||
COMPONENT CURRENT AVAILABLE
|
||||
Kubelet 1 x v1.15.3 v1.16.0
|
||||
|
||||
Upgrade to the latest version in the v1.17 series:
|
||||
|
||||
COMPONENT CURRENT AVAILABLE
|
||||
API Server v1.15.3 v1.16.0
|
||||
Controller Manager v1.15.3 v1.16.0
|
||||
Scheduler v1.15.3 v1.16.0
|
||||
Kube Proxy v1.15.3 v1.16.0
|
||||
CoreDNS 1.6.5 1.6.7
|
||||
Etcd 3.4.3 3.4.3-0
|
||||
|
||||
You can now apply the upgrade by executing the following command:
|
||||
|
||||
kubeadm upgrade apply v1.16.0
|
||||
|
||||
_____________________________________________________________________
|
||||
```
|
||||
* 업그레이드 실행
|
||||
```bash
|
||||
(1.15.x-> 1.16.x) sudo kubeadm upgrade apply v1.16.x
|
||||
|
||||
(1.16.x-> 1.17.x) sudo kubeadm upgrade apply v1.17.x
|
||||
```
|
||||
```bash
|
||||
[upgrade/config] Making sure the configuration is correct:
|
||||
[upgrade/config] Reading configuration from the cluster...
|
||||
[upgrade/config] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -oyaml'
|
||||
[preflight] Running pre-flight checks.
|
||||
[upgrade] Running cluster health checks
|
||||
[upgrade/version] You have chosen to change the cluster version to "v1.16.0"
|
||||
[upgrade/versions] Cluster version: v1.15.3
|
||||
[upgrade/versions] kubeadm version: v1.16.0
|
||||
[upgrade/confirm] Are you sure you want to proceed with the upgrade? [y/N]: y
|
||||
[upgrade/prepull] Will prepull images for components [kube-apiserver kube-controller-manager kube-scheduler etcd]
|
||||
[upgrade/prepull] Prepulling image for component etcd.
|
||||
[upgrade/prepull] Prepulling image for component kube-apiserver.
|
||||
[upgrade/prepull] Prepulling image for component kube-controller-manager.
|
||||
[upgrade/prepull] Prepulling image for component kube-scheduler.
|
||||
[apiclient] Found 1 Pods for label selector k8s-app=upgrade-prepull-kube-controller-manager
|
||||
[apiclient] Found 0 Pods for label selector k8s-app=upgrade-prepull-etcd
|
||||
[apiclient] Found 0 Pods for label selector k8s-app=upgrade-prepull-kube-scheduler
|
||||
[apiclient] Found 1 Pods for label selector k8s-app=upgrade-prepull-kube-apiserver
|
||||
[apiclient] Found 1 Pods for label selector k8s-app=upgrade-prepull-etcd
|
||||
[apiclient] Found 1 Pods for label selector k8s-app=upgrade-prepull-kube-scheduler
|
||||
[upgrade/prepull] Prepulled image for component etcd.
|
||||
[upgrade/prepull] Prepulled image for component kube-apiserver.
|
||||
[upgrade/prepull] Prepulled image for component kube-controller-manager.
|
||||
[upgrade/prepull] Prepulled image for component kube-scheduler.
|
||||
[upgrade/prepull] Successfully prepulled the images for all the control plane components
|
||||
[upgrade/apply] Upgrading your Static Pod-hosted control plane to version "v1.16.0"...
|
||||
|
||||
......
|
||||
|
||||
[apiclient] Found 1 Pods for label selector component=kube-scheduler
|
||||
[upgrade/staticpods] Component "kube-scheduler" upgraded successfully!
|
||||
[upload-config] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
|
||||
[kubelet] Creating a ConfigMap "kubelet-config-1.16" in namespace kube-system with the configuration for the kubelets in the cluster
|
||||
[kubelet-start] Downloading configuration for the kubelet from the "kubelet-config-1.16" ConfigMap in the kube-system namespace
|
||||
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
|
||||
[bootstrap-token] configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials
|
||||
[bootstrap-token] configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token
|
||||
[bootstrap-token] configured RBAC rules to allow certificate rotation for all node client certificates in the cluster
|
||||
[addons] Applied essential addon: CoreDNS
|
||||
[addons] Applied essential addon: kube-proxy
|
||||
|
||||
[upgrade/successful] SUCCESS! Your cluster was upgraded to "v1.16.0". Enjoy!
|
||||
|
||||
[upgrade/kubelet] Now that your control plane is upgraded, please proceed with upgrading your kubelets if you haven't already done so.
|
||||
```
|
||||
* 적용된 cordon을 해제한다.
|
||||
```bash
|
||||
kubectl uncordon <cp-node-name>
|
||||
|
||||
ex) kubectl uncordon k8s-master
|
||||
```
|
||||
* master와 node에 kubelet 및 kubectl을 업그레이드한다.
|
||||
```bash
|
||||
(1.15.x-> 1.16.x) yum install -y kubelet-1.16.x-0 kubectl-1.16.x-0 --disableexcludes=kubernetes
|
||||
|
||||
(1.16.x-> 1.17.x) yum install -y kubelet-1.17.x-0 kubectl-1.17.x-0 --disableexcludes=kubernetes
|
||||
```
|
||||
* kubelet을 재시작 한다.
|
||||
```bash
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl restart kubelet
|
||||
```
|
||||
* 비고 :
|
||||
* master 다중화 구성 클러스터 업그레이드 시에는 다음과 같은 명령어를 실행한다.
|
||||
* 첫번째 컨트롤 플레인 업그레이드 시에는 위에 step을 진행하고, 나머지 컨트롤 플레인 업그레이드 시에는 아래의 명령어를 실행한다.
|
||||
|
||||
* 추가된 master에서 kubeadm을 upgrade 한다.
|
||||
```bash
|
||||
yum install -y kubeadm-설치버전 --disableexcludes=kubernetes
|
||||
|
||||
ex) yum install -y kubeadm-1.16.0-0 --disableexcludes=kubernetes
|
||||
|
||||
ex) yum install -y kubeadm-1.17.6-0 --disableexcludes=kubernetes
|
||||
```
|
||||
* 버전 확인
|
||||
```bash
|
||||
kubeadm version
|
||||
```
|
||||
* node drain
|
||||
* 추가 컨트롤 플레인에서도 첫번째 컨트롤 플레인 node drain 전 체크 사항을 참고하여 drain 가능한 상태인지 체크한다.
|
||||
* node drain 실행
|
||||
* node drain시 해당 node상의 pod가 evict되기 때문에, pod의 local-data의 경우 보존되지 않음
|
||||
```bash
|
||||
kubectl drain <node-to-drain> --ignore-daemonsets --delete-local-data
|
||||
|
||||
ex) kubectl drain k8s-master2 --ignore-daemonsets --delete-local-data
|
||||
```
|
||||
* 추가 컨트롤 프레인에서는 해당 명령어를 실행하지 않는다. (sudo kubeadm upgrade plan)
|
||||
* sudo kubeadm upgrade apply 명령어 대신에 sudo kubeadm upgrade node 명령어를 실행한다.
|
||||
```bash
|
||||
sudo kubeadm upgrade node
|
||||
```
|
||||
* 적용된 cordon을 해제한다.
|
||||
```bash
|
||||
kubectl uncordon <cp-node-name>
|
||||
|
||||
ex) kubectl uncordon k8s-master2
|
||||
```
|
||||
* master와 node에 kubelet 및 kubectl을 업그레이드한다.
|
||||
```bash
|
||||
(1.15.x-> 1.16.x) yum install -y kubelet-1.16.x-0 kubectl-1.16.x-0 --disableexcludes=kubernetes
|
||||
|
||||
(1.16.x-> 1.17.x) yum install -y kubelet-1.17.x-0 kubectl-1.17.x-0 --disableexcludes=kubernetes
|
||||
```
|
||||
* kubelet을 재시작 한다.
|
||||
```bash
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl restart kubelet
|
||||
```
|
||||
* 업그레이드 후 노드가 ready -> not ready 상태로 바뀐 경우
|
||||
* Failed to initialize CSINode: error updating CSINode annotation: timed out waiting for the condition; caused by: the server could not find the requested resource
|
||||
```bash
|
||||
sudo vi /var/lib/kubelet/config.yaml에 아래 옵션 추가
|
||||
|
||||
featureGates:
|
||||
CSIMigration: false
|
||||
|
||||
sudo systemctl restart kubelet
|
||||
```
|
||||
* 업그레이드시 runtime 변경을 하는 경우 (docker -> cri-o)
|
||||
* crio 설치는 https://github.com/tmax-cloud/hypercloud-install-guide/tree/master/K8S_Master#step-1-cri-o-%EC%84%A4%EC%B9%98를 참조한다.
|
||||
```bash
|
||||
systemctl stop kubelet
|
||||
|
||||
sudo vi /var/lib/kubelet/kubeadm-flags.env에 옵션 변경
|
||||
|
||||
기존 (docker) : KUBELET_KUBEADM_ARGS="--cgroup-driver=cgroupfs --network-plugin=cni --pod-infra-container-image=k8s.gcr.io/pause:3.1
|
||||
변경 (cri-o) : KUBELET_KUBEADM_ARGS="--container-runtime=remote --cgroup-driver=systemd --container-runtime-endpoint=/var/run/crio/crio.sock"
|
||||
|
||||
systemctl restart kubelet
|
||||
systemctl restart docker ( #docker image registry node는 systemctl restart docker 명령어를 실행한다. )
|
||||
```
|
||||
|
||||
## Step1. kubernetes node upgrade
|
||||
* 워커 노드의 업그레이드 절차는 워크로드를 실행하는 데 필요한 최소 용량을 보장하면서, 한 번에 하나의 노드 또는 한 번에 몇 개의 노드로 실행해야 한다.
|
||||
* 모든 worker node에서 kubeadm을 업그레이드한다.
|
||||
```bash
|
||||
yum install -y kubeadm-설치버전 --disableexcludes=kubernetes
|
||||
|
||||
ex) (1.15.x-> 1.16.x) yum install -y kubeadm-1.16.x-0 --disableexcludes=kubernetes
|
||||
|
||||
ex) (1.15.x-> 1.16.x) yum install -y kubeadm-1.17.x-0 --disableexcludes=kubernetes
|
||||
```
|
||||
* node drain
|
||||
* node drain 전 체크 사항
|
||||
* PDB가 존재하는 Pod가 drain하려는 node에 생성되어있는 경우 evict가 제한 되기 때문에, 아래 명령어로 drain이 가능한 상태인지 확인한다.
|
||||
```bash
|
||||
kubectl get pdb -A
|
||||
or
|
||||
kubectl get pdb <pdb-name> -oyaml
|
||||
```
|
||||
* ALLOWED DISRUPTIONS 및 drain 시키려는 node의 pod 상태를 확인한다.
|
||||
* PDB의 ALLOWED DISRUPTIONS가 drain을 시도하는 node에 뜬 pod(pdb 설정 pod) 개수보다 적을 경우 아래와 같이 다른 노드로 재스케줄링이 필요하다.
|
||||
* ex) virt-api pod가 drain하려는 node에 2개 떠있는데, ALLOWED DISRUPTIONS는 0 또는 1일 경우
|
||||
* 해당 조건에 만족하지 않는 경우 'Cannot evict pod as it would violate the pod's disruption budget' 와 같은 에러가 발생할 수 있다.
|
||||
* 해결 방법
|
||||
* 1) 해당 Pod를 다른 Node로 재스케줄링을 시도한다.
|
||||
```bash
|
||||
kubectl delete pod <pod-name>
|
||||
```
|
||||
* 2) 다른 Node의 리소스 부족, noScheduling 설정 등으로 인해 a번 재스케줄링이 불가할 경우엔 PDB 데이터를 삭제하고 drain한 후에 PDB 데이터를 복구한다.
|
||||
```bash
|
||||
kubectl get pdb <pdb-name> -o yaml > pdb-backup.yaml
|
||||
kubectl drain <node-to-drain> --ignore-daemonsets --delete-local-data
|
||||
kubectl apply -f pdb-backup.yaml
|
||||
```
|
||||
* node drain 실행
|
||||
* warning : node drain시 해당 node상의 pod가 evict되기 때문에, pod의 local-data의 경우 보존되지 않음
|
||||
```bash
|
||||
kubectl drain <node-to-drain> --ignore-daemonsets --delete-local-data
|
||||
|
||||
ex) kubectl drain k8s-node --ignore-daemonsets --delete-local-data
|
||||
```
|
||||
* kubelet 구성 업그레이드
|
||||
```bash
|
||||
sudo kubeadm upgrade node
|
||||
```
|
||||
* kubelet과 kubectl 업그레이드
|
||||
```bash
|
||||
(1.15.x-> 1.16.x) yum install -y kubelet-1.16.x-0 kubectl-1.16.x-0 --disableexcludes=kubernetes
|
||||
|
||||
(1.16.x-> 1.17.x) yum install -y kubelet-1.17.x-0 kubectl-1.17.x-0 --disableexcludes=kubernetes
|
||||
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl restart kubelet
|
||||
```
|
||||
* 적용된 cordon을 해제한다.
|
||||
```bash
|
||||
kubectl uncordon <cp-node-name>
|
||||
|
||||
ex) kubectl uncordon k8s-node
|
||||
```
|
||||
* 비고 :
|
||||
* 1.16.x -> 1.17.x로 업그레이드시 버전에 맞추어 위에 작업을 실행한다.
|
||||
* 업그레이드 후 노드가 ready -> not ready 상태로 바뀐 경우
|
||||
* Failed to initialize CSINode: error updating CSINode annotation: timed out waiting for the condition; caused by: the server could not find the requested resource
|
||||
```bash
|
||||
sudo vi /var/lib/kubelet/config.yaml에 아래 옵션 추가
|
||||
|
||||
featureGates:
|
||||
CSIMigration: false
|
||||
|
||||
sudo systemctl restart kubelet
|
||||
```
|
||||
* 업그레이드시 runtime 변경을 하는 경우 (docker -> cri-o)
|
||||
* crio 설치는 https://github.com/tmax-cloud/hypercloud-install-guide/tree/master/K8S_Master#step-1-cri-o-%EC%84%A4%EC%B9%98를 참조한다.
|
||||
```bash
|
||||
systemctl stop kubelet
|
||||
|
||||
sudo vi /var/lib/kubelet/kubeadm-flags.env에 옵션 변경
|
||||
|
||||
기존 (docker) : KUBELET_KUBEADM_ARGS="--cgroup-driver=cgroupfs --network-plugin=cni --pod-infra-container-image=k8s.gcr.io/pause:3.1
|
||||
변경 (cri-o) : KUBELET_KUBEADM_ARGS="--container-runtime=remote --cgroup-driver=systemd --container-runtime-endpoint=/var/run/crio/crio.sock"
|
||||
|
||||
systemctl restart kubelet
|
||||
systemctl stop docker ( #docker image registry node는 systemctl restart docker 명령어를 실행한다. )
|
||||
|
||||
```
|
||||
399
README_dualstack.md
Normal file
@@ -0,0 +1,399 @@
|
||||
|
||||
# k8s-master 설치 가이드
|
||||
|
||||
## 구성 요소 및 버전
|
||||
* cri-o (v1.17.4)
|
||||
* kubeadm, kubelet, kubectl (v1.17.6)
|
||||
* k8s.gcr.io/kube-apiserver:v1.17.6
|
||||
* k8s.gcr.io/kube-proxy:v1.17.6
|
||||
* k8s.gcr.io/kube-scheduler:v1.17.6
|
||||
* k8s.gcr.io/kube-controller-manager:v1.17.6
|
||||
* k8s.gcr.io/etcd:3.4.3-0
|
||||
* k8s.gcr.io/pause:3.1
|
||||
* k8s.gcr.io/coredns:1.6.5
|
||||
|
||||
## Prerequisites
|
||||
## 폐쇄망 설치 가이드
|
||||
|
||||
1. **폐쇄망에서 설치하는 경우** 아래 가이드를 참고 하여 image registry를 먼저 구축한다.
|
||||
* https://github.com/tmax-cloud/hypercloud-install-guide/tree/master/Image_Registry
|
||||
2. 사용하는 image repository에 k8s 설치 시 필요한 이미지를 push한다.
|
||||
* 작업 디렉토리 생성 및 환경 설정
|
||||
```bash
|
||||
$ mkdir -p ~/k8s-install
|
||||
$ cd ~/k8s-install
|
||||
```
|
||||
* 외부 네트워크 통신이 가능한 환경에서 필요한 이미지를 다운받는다.
|
||||
```bash
|
||||
$ sudo docker pull k8s.gcr.io/kube-proxy:v1.17.6
|
||||
$ sudo docker pull k8s.gcr.io/kube-apiserver:v1.17.6
|
||||
$ sudo docker pull k8s.gcr.io/kube-controller-manager:v1.17.6
|
||||
$ sudo docker pull k8s.gcr.io/kube-scheduler:v1.17.6
|
||||
$ sudo docker pull k8s.gcr.io/etcd:3.4.3-0
|
||||
$ sudo docker pull k8s.gcr.io/coredns:1.6.5
|
||||
$ sudo docker pull k8s.gcr.io/pause:3.1
|
||||
```
|
||||

|
||||
* docker image를 tar로 저장한다.
|
||||
```bash
|
||||
$ sudo docker save -o kube-proxy.tar k8s.gcr.io/kube-proxy:v1.17.6
|
||||
$ sudo docker save -o kube-controller-manager.tar k8s.gcr.io/kube-controller-manager:v1.17.6
|
||||
$ sudo docker save -o etcd.tar k8s.gcr.io/etcd:3.4.3-0
|
||||
$ sudo docker save -o coredns.tar k8s.gcr.io/coredns:1.6.5
|
||||
$ sudo docker save -o kube-scheduler.tar k8s.gcr.io/kube-scheduler:v1.17.6
|
||||
$ sudo docker save -o kube-apiserver.tar k8s.gcr.io/kube-apiserver:v1.17.6
|
||||
$ sudo docker save -o pause.tar k8s.gcr.io/pause:3.1
|
||||
```
|
||||

|
||||
3. 위의 과정에서 생성한 tar 파일들을 폐쇄망 환경으로 이동시킨 뒤 사용하려는 registry에 이미지를 push한다.
|
||||
```bash
|
||||
$ sudo docker load -i kube-apiserver.tar
|
||||
$ sudo docker load -i kube-scheduler.tar
|
||||
$ sudo docker load -i kube-controller-manager.tar
|
||||
$ sudo docker load -i kube-proxy.tar
|
||||
$ sudo docker load -i etcd.tar
|
||||
$ sudo docker load -i coredns.tar
|
||||
$ sudo docker load -i pause.tar
|
||||
```
|
||||

|
||||
```bash
|
||||
$ sudo docker tag k8s.gcr.io/kube-apiserver:v1.17.6 ${REGISTRY}/k8s.gcr.io/kube-apiserver:v1.17.6
|
||||
$ sudo docker tag k8s.gcr.io/kube-proxy:v1.17.6 ${REGISTRY}/k8s.gcr.io/kube-proxy:v1.17.6
|
||||
$ sudo docker tag k8s.gcr.io/kube-controller-manager:v1.17.6 ${REGISTRY}/k8s.gcr.io/kube-controller-manager:v1.17.6
|
||||
$ sudo docker tag k8s.gcr.io/etcd:3.4.3-0 ${REGISTRY}/k8s.gcr.io/etcd:3.4.3-0
|
||||
$ sudo docker tag k8s.gcr.io/coredns:1.6.5 ${REGISTRY}/k8s.gcr.io/coredns:1.6.5
|
||||
$ sudo docker tag k8s.gcr.io/kube-scheduler:v1.17.6 ${REGISTRY}/k8s.gcr.io/kube-scheduler:v1.17.6
|
||||
$ sudo docker tag k8s.gcr.io/pause:3.1 ${REGISTRY}/k8s.gcr.io/pause:3.1
|
||||
```
|
||||

|
||||
```bash
|
||||
$ sudo docker push ${REGISTRY}/k8s.gcr.io/kube-apiserver:v1.17.6
|
||||
$ sudo docker push ${REGISTRY}/k8s.gcr.io/kube-proxy:v1.17.6
|
||||
$ sudo docker push ${REGISTRY}/k8s.gcr.io/kube-controller-manager:v1.17.6
|
||||
$ sudo docker push ${REGISTRY}/k8s.gcr.io/etcd:3.4.3-0
|
||||
$ sudo docker push ${REGISTRY}/k8s.gcr.io/coredns:1.6.5
|
||||
$ sudo docker push ${REGISTRY}/k8s.gcr.io/kube-scheduler:v1.17.6
|
||||
$ sudo docker push ${REGISTRY}/k8s.gcr.io/pause:3.1
|
||||
```
|
||||

|
||||
```bash
|
||||
$ curl ${REGISTRY}/v2/_catalog
|
||||
```
|
||||

|
||||
* 비고 :
|
||||
* 위 내용은 2개이상의 마스터 구축시 마스터 1개에서만 진행한다.
|
||||
## Install Steps
|
||||
0. [환경 설정](https://github.com/tmax-cloud/hypercloud-install-guide/tree/master/K8S_Master#step0-%ED%99%98%EA%B2%BD-%EC%84%A4%EC%A0%95)
|
||||
1. [cri-o 설치](https://github.com/tmax-cloud/hypercloud-install-guide/tree/master/K8S_Master#step-1-cri-o-%EC%84%A4%EC%B9%98)
|
||||
2. [kubeadm, kubelet, kubectl 설치](https://github.com/tmax-cloud/hypercloud-install-guide/tree/master/K8S_Master#step-2-kubeadm-kubelet-kubectl-%EC%84%A4%EC%B9%98)
|
||||
3. [kubernetes cluster 구성](https://github.com/tmax-cloud/hypercloud-install-guide/tree/master/K8S_Master#step-3-kubernetes-cluster-%EA%B5%AC%EC%84%B1)
|
||||
3-1. [kubernetes cluster 구성(master 다중화)](https://github.com/tmax-cloud/hypercloud-install-guide/tree/master/K8S_Master#step-3-1-kubernetes-cluster-%EB%8B%A4%EC%A4%91%ED%99%94-%EA%B5%AC%EC%84%B1%EC%9D%84-%EC%9C%84%ED%95%9C-keepalived-%EC%84%A4%EC%B9%98)
|
||||
|
||||
## Step0. 환경 설정
|
||||
* 목적 : `k8s 설치 진행을 위한 os 환경 설정`
|
||||
* 순서 :
|
||||
* os hostname을 설정한다.
|
||||
```bash
|
||||
sudo hostnamectl set-hostname k8s-master
|
||||
```
|
||||
* hostname과 ip를 등록한다.
|
||||
* sudo vi /etc/hosts
|
||||
```bash
|
||||
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
|
||||
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
|
||||
|
||||
172.22.5.2 k8s-master
|
||||
```
|
||||
* 방화벽(firewall)을 해제한다.
|
||||
```bash
|
||||
sudo systemctl stop firewalld
|
||||
sudo systemctl disable firewalld
|
||||
```
|
||||
* 스왑 메모리를 비활성화 한다.
|
||||
```bash
|
||||
sudo swapoff -a
|
||||
```
|
||||
* 스왑 메모리 비활성화 영구설정
|
||||
* sudo vi /etc/fstab
|
||||
```bash
|
||||
swap 관련 부분 주석처리
|
||||
# /dev/mapper/centos-swap swap swap defaults 0
|
||||
```
|
||||

|
||||
* SELinux 설정을 해제한다.
|
||||
```bash
|
||||
sudo setenforce 0
|
||||
sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
|
||||
```
|
||||
* crio 사용 전 환경 설정
|
||||
```bash
|
||||
sudo modprobe overlay
|
||||
sudo modprobe br_netfilter
|
||||
|
||||
sudo cat << "EOF" | sudo tee -a /etc/sysctl.d/99-kubernetes-cri.conf
|
||||
net.bridge.bridge-nf-call-iptables = 1
|
||||
net.ipv4.ip_forward = 1
|
||||
net.bridge.bridge-nf-call-ip6tables = 1
|
||||
EOF
|
||||
|
||||
sudo sysctl --system
|
||||
```
|
||||
## Step 1. cri-o 설치
|
||||
* 목적 : `k8s container runtime 설치`
|
||||
* 순서 :
|
||||
* cri-o를 설치한다.
|
||||
* (폐쇄망) 아래 주소를 참조하여 패키지 레포를 등록 후 crio를 설치한다.
|
||||
* https://github.com/tmax-cloud/hypercloud-install-guide/tree/master/Package#step-1-local-repository-%EA%B5%AC%EC%B6%95
|
||||
```bash
|
||||
sudo yum -y install cri-o
|
||||
sudo systemctl enable crio
|
||||
sudo systemctl start crio
|
||||
```
|
||||
* (외부망) crio 버전 지정 및 레포를 등록 후 crio를 설치한다.
|
||||
```bash
|
||||
VERSION=1.17
|
||||
sudo curl -L -o /etc/yum.repos.d/devel:kubic:libcontainers:stable.repo https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable/CentOS_7/devel:kubic:libcontainers:stable.repo
|
||||
sudo curl -L -o /etc/yum.repos.d/devel:kubic:libcontainers:stable:cri-o:${VERSION}.repo https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable:cri-o:${VERSION}/CentOS_7/devel:kubic:libcontainers:stable:cri-o:${VERSION}.repo
|
||||
|
||||
sudo yum -y install cri-o
|
||||
sudo systemctl enable crio
|
||||
sudo systemctl start crio
|
||||
```
|
||||
* cri-o 설치를 확인한다.
|
||||
```bash
|
||||
sudo systemctl status crio
|
||||
rpm -qi cri-o
|
||||
```
|
||||

|
||||
* 비고 :
|
||||
* 추후 설치예정인 network plugin과 crio의 가상 인터페이스 충돌을 막기위해 cri-o의 default 인터페이스 설정을 제거한다.
|
||||
```bash
|
||||
sudo rm -rf /etc/cni/net.d/100-crio-bridge.conf
|
||||
sudo rm -rf /etc/cni/net.d/200-loopback.conf
|
||||
```
|
||||
* 폐쇄망 환경에서 private registry 접근을 위해 crio.conf 내용을 수정한다.
|
||||
* insecure_registry, registries, plugin_dirs 내용을 수정한다.
|
||||
* sudo vi /etc/crio/crio.conf
|
||||
* registries = ["{registry}:{port}" , "docker.io"]
|
||||
* insecure_registries = ["{registry}:{port}"]
|
||||
* plugin_dirs : "/opt/cni/bin" 추가
|
||||
* (폐쇄망) pause_image : "k8s.gcr.io/pause:3.1" 을 "{registry}:{port}/k8s.gcr.io/pause:3.1" 로 변경
|
||||

|
||||
|
||||
* registries.conf 내용을 수정한다.
|
||||
* sudo vi /etc/containers/registries.conf
|
||||
```bash
|
||||
unqualified-search-registries = ['registry.fedoraproject.org', 'registry.access.redhat.com', 'registry.centos.org', 'docker.io', '{registry}:{port}']
|
||||
ex) unqualified-search-registries = ['registry.fedoraproject.org', 'registry.access.redhat.com', 'registry.centos.org', 'docker.io', '172.22.5.2:5000']
|
||||
```
|
||||
* crio를 재시작 한다.
|
||||
```bash
|
||||
sudo systemctl restart crio
|
||||
```
|
||||
## Step 2. kubeadm, kubelet, kubectl 설치
|
||||
* 목적 : `Kubernetes 구성을 위한 kubeadm, kubelet, kubectl 설치한다.`
|
||||
* 순서:
|
||||
* CRI-O 메이저와 마이너 버전은 쿠버네티스 메이저와 마이너 버전이 일치해야 한다.
|
||||
* (폐쇄망) kubeadm, kubectl, kubelet 설치 (v1.17.6)
|
||||
```bash
|
||||
sudo yum install -y kubeadm-1.17.6-0 kubelet-1.17.6-0 kubectl-1.17.6-0
|
||||
|
||||
sudo systemctl enable kubelet
|
||||
```
|
||||
* (외부망) 레포 등록 후 kubeadm, kubectl, kubelet 설치 (v1.17.6)
|
||||
```bash
|
||||
sudo cat << "EOF" | sudo tee -a /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
|
||||
EOF
|
||||
|
||||
sudo yum install -y kubeadm-1.17.6-0 kubelet-1.17.6-0 kubectl-1.17.6-0
|
||||
|
||||
sudo systemctl enable kubelet
|
||||
```
|
||||
|
||||
## Step 3. kubernetes cluster 구성
|
||||
* 목적 : `kubernetes master를 구축한다.`
|
||||
* 순서 :
|
||||
* 쿠버네티스 설치시 필요한 kubeadm-config를 작성한다.
|
||||
* vi kubeadm-config.yaml
|
||||
```bash
|
||||
apiVersion: kubeadm.k8s.io/v1beta2
|
||||
kind: InitConfiguration
|
||||
localAPIEndpoint:
|
||||
advertiseAddress: {api server IP}
|
||||
bindPort: 6443
|
||||
nodeRegistration:
|
||||
criSocket: /var/run/crio/crio.sock
|
||||
---
|
||||
apiVersion: kubeadm.k8s.io/v1beta2
|
||||
kind: ClusterConfiguration
|
||||
kubernetesVersion: v1.17.6
|
||||
controlPlaneEndpoint: {endpoint IP}:6443
|
||||
imageRepository: {registry}/k8s.gcr.io
|
||||
networking:
|
||||
serviceSubnet: 10.96.0.0/16,fd00:10:96::/112
|
||||
podSubnet: 10.244.0.0/16,fd00:10:20::/72
|
||||
featureGates:
|
||||
IPv6DualStack: true
|
||||
---
|
||||
apiVersion: kubelet.config.k8s.io/v1beta1
|
||||
kind: KubeletConfiguration
|
||||
cgroupDriver: systemd
|
||||
---
|
||||
apiVersion: kubeproxy.config.k8s.io/v1alpha1
|
||||
kind: KubeProxyConfiguration
|
||||
mode: ipvs
|
||||
```
|
||||
* kubernetesVersion : kubernetes version
|
||||
* advertiseAddress : API server IP ( master IP )
|
||||
* 해당 master 노드의 IP
|
||||
* controlPlaneEndpoint : endpoint IP ( master IP or virtual IP) , port는 반드시 6443으로 설정
|
||||
* 1개의 마스터 : master IP , 2개 이상의 마스터 구축시 : virtual IP
|
||||
* serviceSubnet : "${SERVICE_IPV4_POOL}/${CIDR},${SERVICE_IPV6_POOL}/${CIDR}"
|
||||
* podSubnet : "${POD_IPV4_POOL}/${CIDR},${POD_IPV6_POOL}/${CIDR}"
|
||||
* imageRepository : "${registry} / docker hub name"
|
||||
* IPv6DualStack: true, dual stack 기능이 베타 버전이라서 기본값으로는 비활성화이기 때문에 활성화 시키는 세팅(추후 기본으로 활성화 되면 빠져야 함)
|
||||
* cgroupDriver: cgroup driver systemd 변경
|
||||
* mode: ipvs, dual stack 기능은 kube-proxy ipvs 모드에서만 동작
|
||||
|
||||
* kubeadm init (2개 이상 마스터 구축시에는 아래 가이드 참조)
|
||||
```bash
|
||||
sudo kubeadm init --config=kubeadm-config.yaml
|
||||
```
|
||||
* 마스터 다중화 진행시 아래 마스터 다중화 가이드로 설치를 진행한다.
|
||||
* [마스터 다중화 가이드](https://github.com/tmax-cloud/hypercloud-install-guide/tree/master/K8S_Master#step-3-1-kubernetes-cluster-%EB%8B%A4%EC%A4%91%ED%99%94-%EA%B5%AC%EC%84%B1%EC%9D%84-%EC%9C%84%ED%95%9C-keepalived-%EC%84%A4%EC%B9%98)
|
||||
|
||||

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

|
||||
* 확인
|
||||
```bash
|
||||
kubectl get nodes
|
||||
```
|
||||

|
||||
```bash
|
||||
kubectl get pods -A -o wide
|
||||
```
|
||||

|
||||
* 비고 :
|
||||
* master에도 pod 스케줄을 가능하게 하려면 master taint를 제거한다
|
||||
```bash
|
||||
kubectl taint node [master hostname] node-role.kubernetes.io/master:NoSchedule-
|
||||
ex) kubectl taint node k8s- node-role.kubernetes.io/master:NoSchedule-
|
||||
```
|
||||
|
||||
## Step 3-1. kubernetes cluster 다중화 구성을 위한 Keepalived 설치
|
||||
* 목적 : `K8S cluster의 Master 다중화 구성을 위한 Keepalived를 설치 및 설정한다`
|
||||
* 순서 :
|
||||
* Keepalived 설치
|
||||
```bash
|
||||
sudo yum install -y keepalived
|
||||
```
|
||||
|
||||
* Keepalived 설정
|
||||
```bash
|
||||
sudo vi /etc/keepalived/keepalived.conf
|
||||
|
||||
vrrp_instance VI_1 {
|
||||
state {MASTER or BACKUP}
|
||||
interface {network interface}
|
||||
virtual_router_id {virtual router id}
|
||||
priority {priority}
|
||||
advert_int 1
|
||||
nopreempt
|
||||
authentication {
|
||||
auth_type PASS
|
||||
auth_pass $ place secure password here.
|
||||
}
|
||||
virtual_ipaddress {
|
||||
{VIP}
|
||||
}
|
||||
}
|
||||
```
|
||||

|
||||
* interface : network interface 이름 확인 (ip a 명령어로 확인) ex) enp0s8
|
||||
* state : master or backup으로 설정, 하나의 master에만 master를 설정하고 나머지 master에는 backup으로 설정
|
||||
* priority : Master 우선순위
|
||||
* priority 값이 높으면 최우선적으로 Master 역할 수행
|
||||
* 각 Master마다 다른 priority 값으로 수정
|
||||
* ex) master1 priority 100, master2 priority 99, master3 priority 98
|
||||
* virtual_ipaddress : virtual ip(VIP) 설정
|
||||
* virtual_router_id : vritual router id ex) 50
|
||||
|
||||
* keepalived 재시작 및 상태 확인
|
||||
```bash
|
||||
sudo systemctl restart keepalived
|
||||
sudo systemctl enable keepalived
|
||||
sudo systemctl status keepalived
|
||||
|
||||
```
|
||||
|
||||
* network interface 확인
|
||||
```bash
|
||||
ip a
|
||||
```
|
||||
|
||||
* 설정한 VIP 확인 가능, 여러 마스터 중 하나만 보임.
|
||||
* inet {VIP}/32 scope global eno1
|
||||

|
||||
|
||||
## Step 3-2. docker 설치 및 설정
|
||||
* 목적 : `구성한 docker registry에 접근을 위해 docker를 설치한다.`
|
||||
* 생성 순서 :
|
||||
* 다른 구성하는 마스터에 docker를 설치한다.
|
||||
```bash
|
||||
$ sudo yum install -y docker-ce
|
||||
$ sudo systemctl start docker
|
||||
$ sudo systemctl enable docker
|
||||
```
|
||||
* docker damon에 insecure-registries를 등록한다.
|
||||
* sudo vi /etc/docker/daemon.json
|
||||
```bash
|
||||
{
|
||||
"insecure-registries": ["{IP}:5000"]
|
||||
}
|
||||
```
|
||||
* docker를 재실행하고 status를 확인한다.
|
||||
```bash
|
||||
$ sudo systemctl restart docker
|
||||
$ sudo systemctl status docker
|
||||
```
|
||||
|
||||
## Step 3-3. kubernetes cluster 다중화 구성 설정
|
||||
* 목적 : `K8S cluster의 Master 다중화를 구성한다`
|
||||
* 순서 :
|
||||
* kubeadm-config.yaml 파일로 kubeadm 명령어 실행한다.
|
||||
* Master 다중구성시 --upload-certs 옵션은 반드시 필요.
|
||||
* join 시에 --cri-socket=/var/run/crio/crio.sock 옵션을 추가하여 실행한다.
|
||||
```bash
|
||||
sudo kubeadm init --config=kubeadm-config.yaml --upload-certs
|
||||
sudo kubeadm join {IP}:{PORT} --token ~~ discovery-token-ca-cert-hash --control-plane --certificate-key ~~ (1) --cri-socket=/var/run/crio/crio.sock
|
||||
sudo kubeadm join {IP}:{PORT} --token ~~ discovery-token-ca-cert-hash --cri-socket=/var/run/crio/crio.sock (2)
|
||||
```
|
||||

|
||||
* 해당 옵션은 certificates를 control-plane으로 upload하는 옵션
|
||||
* 해당 옵션을 설정하지 않을 경우, 모든 Master 노드에서 key를 복사해야 함
|
||||
* Master 단일구성과는 다르게, --control-plane --certificate-key 옵션이 추가된 명령어가 출력됨
|
||||
* (1)처럼 Master 다중구성을 위한 hash 값을 포함한 kubeadm join 명령어가 출력되므로 해당 명령어를 복사하여 다중구성에 포함시킬 다른 Master에서 실행
|
||||
* (2)처럼 Worker의 join을 위한 명령어도 출력되므로 Worker 노드 join시 사용, crio 사용시 --cri-socket 옵션 추가
|
||||
```bash
|
||||
sudo kubeadm join 172.22.5.2:6443 --token 2cks7n.yvojnnnq1lyz1qud \ --discovery-token-ca-cert-hash sha256:efba18bb4862cbcb54fb643a1b7f91c25e08cfc1640e5a6fffa6de83e4c76f07 \ --control-plane --certificate-key f822617fcbfde09dff35c10e388bc881904b5b6c4da28f3ea8891db2d0bd3a62 --cri-socket=/var/run/crio/crio.sock
|
||||
```
|
||||
|
||||
* kubernetes config
|
||||
```bash
|
||||
mkdir -p $HOME/.kube
|
||||
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
|
||||
sudo chown $(id -u):$(id -g) $HOME/.kube/config
|
||||
```
|
||||
BIN
figure/check.PNG
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
BIN
figure/crio.PNG
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
figure/crio_config.PNG
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
figure/dockerimages.PNG
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
figure/dockerload.PNG
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
figure/dockersave.PNG
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
figure/fstab.PNG
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
figure/init.PNG
Normal file
|
After Width: | Height: | Size: 71 KiB |
BIN
figure/init_success.PNG
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
figure/ipa.PNG
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
figure/keepalived.PNG
Normal file
|
After Width: | Height: | Size: 7.4 KiB |
BIN
figure/kubeadm init success.PNG
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
figure/kubeadm init.PNG
Normal file
|
After Width: | Height: | Size: 71 KiB |
BIN
figure/kubectl get nodes.PNG
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
BIN
figure/kubectl get pods -A.PNG
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
figure/kubeinit.PNG
Normal file
|
After Width: | Height: | Size: 66 KiB |
BIN
figure/load.PNG
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
figure/master2.PNG
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
figure/nodes.PNG
Normal file
|
After Width: | Height: | Size: 4.0 KiB |
BIN
figure/noding.PNG
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
figure/pods.PNG
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
figure/pull.PNG
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
figure/push.PNG
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
figure/registry.PNG
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
figure/rpm.PNG
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
figure/save.PNG
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
BIN
figure/success.PNG
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
figure/tag.PNG
Normal file
|
After Width: | Height: | Size: 39 KiB |
40
installer/README.md
Normal file
@@ -0,0 +1,40 @@
|
||||
|
||||
|
||||
# k8s-master installer 사용법
|
||||
|
||||
## 구성 요소 및 버전
|
||||
|
||||
## Prerequisites
|
||||
* 해당 installer는 폐쇄망 기준 가이드입니다.
|
||||
* OS 설치 및 package repo를 아래 가이드에 맞춰 설치합니다.
|
||||
* https://github.com/tmax-cloud/hypercloud-install-guide/tree/master/Package#os-%EC%84%A4%EC%B9%98--package-repo-%EA%B5%AC%EC%B6%95-%EA%B0%80%EC%9D%B4%EB%93%9C
|
||||
* image registry를 아래 가이드에 맞춰 구축합니다.
|
||||
* https://github.com/tmax-cloud/hypercloud-install-guide/tree/master/Image_Registry#image-registry-%EC%84%A4%EC%B9%98-%EA%B0%80%EC%9D%B4%EB%93%9C
|
||||
* image registry에 이미지를 push 합니다.
|
||||
* https://github.com/tmax-cloud/hypercloud-install-guide/tree/master/K8S_Master#%ED%8F%90%EC%87%84%EB%A7%9D-%EC%84%A4%EC%B9%98-%EA%B0%80%EC%9D%B4%EB%93%9C
|
||||
|
||||
## 폐쇄망 설치 가이드
|
||||
|
||||
## Step0. k8s.config 설정
|
||||
* 목적 : `k8s 설치 진행을 위한 k8s config 설정`
|
||||
* 순서 :
|
||||
* 환경에 맞는 config 내용을 작성합니다.
|
||||
* imageRegistry={IP}:{PORT}
|
||||
* ex : imageRegistry=172.22.5.2:5000
|
||||
* crioVersion={crio version}
|
||||
* ex : crioVersion=1.17
|
||||
* k8sVersion={kubernetes version}
|
||||
* ex : k8sVersion=1.17.6
|
||||
* apiServer={kubernetes API server ip}
|
||||
* ex : apiServer=172.21.7.2
|
||||
* podSubnet={POD_IP_POOL}/{CIDR}
|
||||
* ex : podSubnet=10.244.0.0/16
|
||||
|
||||
## Step1. installer 실행
|
||||
* 목적 : `k8s 설치 진행을 위한 shell script 실행`
|
||||
* 순서 :
|
||||
```bash
|
||||
sudo ./k8s_infra_installer.sh up
|
||||
```
|
||||
* 비고 :
|
||||
* k8s.config, k8s_infra_installer.sh파일과 yaml 디렉토리는 같은 디렉토리 내에에 있어야 합니다.
|
||||
27
installer/k8s.config
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
#------------------------------------------------------------------
|
||||
# ex : imageRegistry={IP}:{PORT}
|
||||
# ex : crioVersion={crio version}
|
||||
# ex : k8sVersion={kubernetes version}
|
||||
# ex : apiServer={kubernetes API server ip}
|
||||
# ex : podSubnet={POD_IP_POOL}/{CIDR}
|
||||
#------------------------------------------------------------------
|
||||
#------------------------------------------------------------------
|
||||
# ex : imageRegistry=172.22.5.2:5000
|
||||
# ex : crioVersion=1.17
|
||||
# ex : k8sVersion=1.17.6
|
||||
# ex : apiServer=172.21.7.2
|
||||
# ex : podSubnet=10.244.0.0/16
|
||||
#------------------------------------------------------------------
|
||||
|
||||
#image registry
|
||||
imageRegistry=172.22.5.2:5000
|
||||
|
||||
#crio
|
||||
crioVersion=1.17
|
||||
|
||||
#kubernetes
|
||||
k8sVersion=1.17.6
|
||||
apiServer=172.22.5.2
|
||||
podSubnet=10.244.0.0/16
|
||||
|
||||
214
installer/k8s_infra_installer.sh
Normal file
@@ -0,0 +1,214 @@
|
||||
#!/bin/bash
|
||||
|
||||
install_dir=$(dirname "$0")
|
||||
. ${install_dir}/k8s.config
|
||||
|
||||
yaml_dir="${install_dir}/yaml"
|
||||
|
||||
os_check=$(awk -F= '/^NAME/{print $2}' /etc/os-release)
|
||||
|
||||
function set_env() {
|
||||
|
||||
echo "========================================================================="
|
||||
echo "======================== set env for kubernetes ========================"
|
||||
echo "========================================================================="
|
||||
|
||||
# centos
|
||||
if [[ ${os_check} == "\"CentOS Linux\"" ]]; then
|
||||
|
||||
# disable firewall
|
||||
sudo systemctl disable firewalld
|
||||
sudo systemctl stop firewalld
|
||||
|
||||
#swapoff
|
||||
sudo swapoff -a
|
||||
sudo sed s/\\/dev\\/mapper\\/centos-swap/#\ \\/dev\\/mapper\\/centos-swap/g -i /etc/fstab
|
||||
|
||||
#selinux mode
|
||||
sudo setenforce 0
|
||||
sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
|
||||
|
||||
#crio-kube set
|
||||
sudo modprobe overlay
|
||||
sudo modprobe br_netfilter
|
||||
|
||||
sudo cat << "EOF" | sudo tee -a /etc/sysctl.d/99-kubernetes-cri.conf
|
||||
net.bridge.bridge-nf-call-iptables = 1
|
||||
net.ipv4.ip_forward = 1
|
||||
net.bridge.bridge-nf-call-ip6tables = 1
|
||||
EOF
|
||||
sudo sysctl --system
|
||||
|
||||
# ubuntu
|
||||
elif [[ ${os_check} = "\"Ubuntu\"" ]]; then
|
||||
|
||||
#swapoff
|
||||
sudo swapoff -a
|
||||
sudo sed s/\\/swap.img/#\ \\/swap.img/g -i /etc/fstab
|
||||
|
||||
# others
|
||||
else
|
||||
sudo echo "This OS is not supported."
|
||||
sudo exit 100
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
function install_crio() {
|
||||
|
||||
echo "========================================================================="
|
||||
echo "========================== start install crio =========================="
|
||||
echo "========================================================================="
|
||||
|
||||
#centos
|
||||
if [[ ${os_check} == "\"CentOS Linux\"" ]]; then
|
||||
|
||||
# install crio
|
||||
sudo yum install -y cri-o
|
||||
sudo systemctl enable crio
|
||||
sudo systemctl start crio
|
||||
|
||||
# check crio
|
||||
sudo systemctl status crio
|
||||
rpm -qi cri-o
|
||||
|
||||
# remove cni0
|
||||
sudo rm -rf /etc/cni/net.d/100-crio-bridge.conf
|
||||
sudo rm -rf /etc/cni/net.d/200-loopback.conf
|
||||
|
||||
# edit crio config
|
||||
sudo sed -i 's/\"\/usr\/libexec\/cni\"/\"\/usr\/libexec\/cni\"\,\"\/opt\/cni\/bin\"/g' /etc/crio/crio.conf
|
||||
sudo sed -i 's/\#insecure\_registries = \"\[\]\"/\insecure\_registries = \[\"{imageRegistry}\"\]/g' /etc/crio/crio.conf
|
||||
sudo sed -i 's/\#registries = \[/registries = \[\"{imageRegistry}\"\]/g' /etc/crio/crio.conf
|
||||
sed -i 's/k8s.gcr.io/{imageRegistry}\/k8s.gcr.io/g' /etc/crio/crio.conf
|
||||
sed -i 's/registry.fedoraproject.org/{imageRegistry}/g' /etc/containers/registries.conf
|
||||
sudo sed -i "s|{imageRegistry}|${imageRegistry}|g" /etc/crio/crio.conf
|
||||
sudo sed -i "s|{imageRegistry}|${imageRegistry}|g" /etc/containers/registries.conf
|
||||
|
||||
sudo systemctl restart crio
|
||||
|
||||
elif [[ ${os_check} = "\"Ubuntu\"" ]]; then
|
||||
|
||||
# install crio
|
||||
sudo apt-get -y install cri-o-${crioVersion}
|
||||
sudo systemctl enable crio.service
|
||||
sudo systemctl start crio.service
|
||||
|
||||
# check crio
|
||||
sudo systemctl status crio
|
||||
|
||||
# remove cni0
|
||||
sudo rm -rf /etc/cni/net.d/100-crio-bridge.conf
|
||||
sudo rm -rf /etc/cni/net.d/200-loopback.conf
|
||||
|
||||
# edit crio config
|
||||
sudo systemctl restart crio
|
||||
|
||||
# others
|
||||
else
|
||||
sudo echo "This OS is not supported."
|
||||
sudo exit 100
|
||||
fi
|
||||
|
||||
|
||||
}
|
||||
|
||||
function install_kube() {
|
||||
|
||||
echo "========================================================================="
|
||||
echo "======================= start install kubernetes ======================"
|
||||
echo "========================================================================="
|
||||
|
||||
#install kubernetes
|
||||
if [[ -z ${k8sVersion} ]]; then
|
||||
k8sVersion=1.17.6
|
||||
else
|
||||
k8sVersion=${k8sVersion}
|
||||
fi
|
||||
|
||||
if [[ -z ${apiServer} ]]; then
|
||||
apiServer=127.0.0.1
|
||||
else
|
||||
apiServer=${apiServer}
|
||||
fi
|
||||
|
||||
if [[ -z ${podSubnet} ]]; then
|
||||
podSubnet=10.244.0.0/16
|
||||
else
|
||||
podSubnet=${podSubnet}
|
||||
fi
|
||||
|
||||
# centos
|
||||
if [[ ${os_check} == "\"CentOS Linux\"" ]]; then
|
||||
|
||||
#install kubernetes components
|
||||
sudo yum install -y kubeadm-${k8sVersion}-0 kubelet-${k8sVersion}-0 kubectl-${k8sVersion}-0
|
||||
sudo systemctl enable --now kubelet
|
||||
# ubuntu
|
||||
elif [[ ${os_check} = "\"Ubuntu\"" ]]; then
|
||||
|
||||
#install kubernetes components
|
||||
sudo apt-get install -y kubeadm-${k8sVersion}-0 kubelet-${k8sVersion}-0 kubectl-${k8sVersion}-0
|
||||
sudo systemctl enable kubelet
|
||||
# others
|
||||
else
|
||||
echo "This OS is not supported."
|
||||
exit 100
|
||||
fi
|
||||
|
||||
sudo echo '1' > /proc/sys/net/ipv4/ip_forward
|
||||
sudo echo '1' > /proc/sys/net/bridge/bridge-nf-call-iptables
|
||||
|
||||
#change kubeadm yaml
|
||||
sudo sed -i "s|{k8sVersion}|v${k8sVersion}|g" ${yaml_dir}/kubeadm-config.yaml
|
||||
sudo sed -i "s|{apiServer}|${apiServer}|g" ${yaml_dir}/kubeadm-config.yaml
|
||||
sudo sed -i "s|{podSubnet}|\"${podSubnet}\"|g" ${yaml_dir}/kubeadm-config.yaml
|
||||
sudo sed -i "s|{imageRegistry}|${imageRegistry}|g" ${yaml_dir}/kubeadm-config.yaml
|
||||
|
||||
# kube init
|
||||
sudo kubeadm init --config=${yaml_dir}/kubeadm-config.yaml --upload-certs
|
||||
|
||||
mkdir -p $HOME/.kube
|
||||
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
|
||||
sudo chown $(id -u):$(id -g) $HOME/.kube/config
|
||||
|
||||
echo "========================================================================="
|
||||
echo "====================== complete install kubernetes ===================="
|
||||
echo "========================================================================="
|
||||
|
||||
}
|
||||
|
||||
function uninstall() {
|
||||
|
||||
kubeadm reset -f
|
||||
|
||||
sudo sed -i "s|v${k8sVersion}|{k8sVersion}|g" ${yaml_dir}/kubeadm-config.yaml
|
||||
sudo sed -i "s|${apiServer}|{apiServer}|g" ${yaml_dir}/kubeadm-config.yaml
|
||||
sudo sed -i "s|\"${podSubnet}\"|{podSubnet}|g" ${yaml_dir}/kubeadm-config.yaml
|
||||
sudo sed -i "s|${imageRegistry}|{imageRegistry}|g" ${yaml_dir}/kubeadm-config.yaml
|
||||
|
||||
sudo rm -rf $HOME/.kube
|
||||
|
||||
}
|
||||
|
||||
function main(){
|
||||
|
||||
case "${1:-}" in
|
||||
up)
|
||||
set_env
|
||||
install_crio
|
||||
install_kube
|
||||
;;
|
||||
delete)
|
||||
uninstall
|
||||
;;
|
||||
*)
|
||||
set +x
|
||||
echo " service list:" >&2
|
||||
echo " $0 up" >&2
|
||||
echo " $0 delete" >&2
|
||||
;;
|
||||
esac
|
||||
}
|
||||
main $1
|
||||
|
||||
20
installer/yaml/kubeadm-config.yaml
Normal file
@@ -0,0 +1,20 @@
|
||||
apiVersion: kubeadm.k8s.io/v1beta2
|
||||
kind: InitConfiguration
|
||||
localAPIEndpoint:
|
||||
advertiseAddress: {apiServer}
|
||||
bindPort: 6443
|
||||
nodeRegistration:
|
||||
criSocket: /var/run/crio/crio.sock
|
||||
---
|
||||
apiVersion: kubeadm.k8s.io/v1beta2
|
||||
kind: ClusterConfiguration
|
||||
kubernetesVersion: {k8sVersion}
|
||||
controlPlaneEndpoint: {apiServer}:6443
|
||||
imageRepository: {imageRegistry}/k8s.gcr.io
|
||||
networking:
|
||||
serviceSubnet: 10.96.0.0/16
|
||||
podSubnet: {podSubnet}
|
||||
---
|
||||
apiVersion: kubelet.config.k8s.io/v1beta1
|
||||
kind: KubeletConfiguration
|
||||
cgroupDriver: systemd
|
||||