KubeCon 2일째 주요 Keynote 내용은 OpenTelemetry, Scalable Kubernetes Cluster, CNCF Tools 입니다.

 

먼저 OpenTelemetry 에서는 아래의 내용들을 이야기 했죠.

 

OpenTelemetry 는 2019년에 발표했는데 OpenCensus 와 OpenTracing 을 합쳤습니다.

OpenTelemetry 가 나온 이유 중 하나는 Vendor lock in 을 피하기 위해서입니다.

 

개념은 아주 간단합니다. Collector 간의 연결입니다.

 

데이터 수집 -> 변경 -> 보내기 형태의 pipeline 구조로 구성됩니다.

 

Collector 가 multiple flow 를 받을 수 있습니다.

 

아래 OpenTelemetry 를 방문하면 더 많은 정보를 얻을 수 있습니다.

 

Scalable Kubernetes Cluster 는 여러 가지 고려 사항을 이야기 했습니다.

15,000 노드 클러스터인 경우에 고려할 사항은 etcd 입니다.

모든 정보가 etcd 에 저장될 텐데 그것을 처리할 수 있는 용량을 항상 고려해야 합니다.

 

apimachinery 도 고려해야 합니다.

많은 리소스들이 저장되어 있는데 이 중에서 리소스를 select 를 할 때 적절하게 조회하고 이를 관리할 수 있는 API 용량이 필요합니다.

 

Networking 부분에서는 돌아다니는 데이터 양을 고려해야 합니다.

Kube-proxy 가 노드마다 떠 있고 endpoint 가 수정될 때 마다 이를 api 서버로 보냅니다. 예를 들어 5000개의 서비스 pod 가 떠 있다면 1M 정도의 데이터 양을 보내는데 노드가 5000개 있다면 보내는 데이터 양은 5G 나 됩니다.

이를 해결하기 위해서 endpoint slicing 을 사용합니다.

 

Secret 과 ConfigMap 이 pod 가 생성되는 로컬에 저장되는 스토리지도 고려해야 합니다.

 

 

 

 

 

Posted by Kubernetes Korea co-leader seungkyua@gmail.com

댓글을 달아 주세요

Contour, A High Performance Multitenant Ingress Controller for Kubernetes - MICHAEL MICHAEL, Steve Sloka, Nick Young, & James Peach, VMware

Kubernetes 에서 north-south 네트워크로 Ingress Controller 는 필수 입니다.

대부분은 Nginx Ingress Controller 를 사용할 텐데 CNCF Incubating Project 로 Contour 를 사용할 수 있습니다.

Contour 는 Envoy 를 중심으로 개발되었네요.

 

Craig 가 구글에서 나와서 만든 Heptio 에서 시작한 프로젝트인데 지금은 bitnami 가 지원하고 있는 것 같습니다.

 

 

아키텍처는 다음과 같습니다.

 

 

세부적인 내용은 https://projectcontour.io/ 를 확인하세요.

소스 Contributing 은 https://github.com/bitnami/charts/tree/master/bitnami/contour  이곳입니다. ^^

 

20201119_0500 Contour, A High Performance Multitenant Ingress Controller for Kubernetes - MICHAEL MICHAEL, Steve Sloka, Nick Young, & James Peach, VMware.pptx
4.24MB



Posted by Kubernetes Korea co-leader seungkyua@gmail.com

댓글을 달아 주세요

1. Diversity-Powered Reilience - Priyanka Sharma

Cloud Native Network Functions (CNF) Working Group Kick off

 

2. Keynote: Are Certifications Worth It? - Cheryl Hung

Certified Kubernetes Security Specialist 신규

 

3. The Cloud Native Journey @Apple - Alena Prokharchyk, Software Engineer, Apple

Apple  에서 Mesos -> Kubernetes 로 옮겨온 이유

애플에서 사용한 CNCF 프로젝트

현재 개발 우선순위

조직 변화

배운 내용

 

 

 

 

 

 

 

Posted by Kubernetes Korea co-leader seungkyua@gmail.com

댓글을 달아 주세요

며칠 전 Kubernetes Cluster 를 v1.16.3 에서 v1.18.5 로 업그레이드 하다가 발견된 이슈를 해결한 내용을 공유합니다.

 

제가 관리하고 있는 Kubernetes 는 Kubespray 로 설치했었고 업그레이드 역시 Kubespray 를 활용했습니다.

Kubespray 는 Kubernetes 설치에 kubeadm 을 사용하는데 kubeadm 은 마이너 버전 차이가 1 을 초과하면 업그레이드를 지원하지 않습니다.

그렇기 때문에 v1.16.x 에서 v1.18.x 로 업그레이드를 하려며 v1.16.x -> v1.17.x -> v1.18.x 로 단계적으로 업그레이드를 해야 합니다.

 

 

기존 설치된 버전은 kubespray 의 release-2.12 브랜치로 v1.16.3 이었고,  kubespray tags/v2.13.2 을 활용하면 v1.17.7 로 업그레이들 할 수 있습니다.

 

 

## deploy 디렉토리로 변경

$ cd ~/deploy/kubespray

 

 

## kubespray 다운로드 (tag 로 할 때)

$ git checkout master

$ git pull

$ git checkout -b tag_v2.13.2 tags/v2.13.2

$ sudo pip install -r requirements.txt

 

 

## inventory 복사 (업그레이드 할 때)

$ rm -rf inventory/k1-seungkyua/group_vars/*

$ cp -r inventory/sample/group_vars inventory/k1-seungkyua

 

 

 

## hosts.ini 수정

$ vi inventory/k1-seungkyua/inventory.ini

[all]

k1-master01 ansible_host=k1-master01 ip=192.168.30.13 iface=eno49

k1-master02 ansible_host=k1-master02 ip=192.168.30.14 iface=ens2f0

k1-master03 ansible_host=k1-master03 ip=192.168.30.15 iface=eno49

k1-node01 ansible_host=k1-node01 ip=192.168.30.12 iface=ens2f0

k1-node02 ansible_host=k1-node02 ip=192.168.30.17 iface=ens2f0

k1-node03 ansible_host=k1-node03 ip=192.168.30.18 iface=ens2f0

k1-node04 ansible_host=k1-node04 ip=192.168.30.21 iface=ens2f0

k1-node05 ansible_host=k1-node05 ip=192.168.30.20 iface=ens2f0

 

[etcd]

k1-master01

k1-master02

k1-master03

 

[kube-master]

k1-master01

k1-master02

k1-master03

 

[kube-node]

k1-node01

k1-node02

k1-node03

k1-node04

k1-node05

 

[calico-rr]

 

[k8s-cluster:children]

kube-master

kube-node

calico-rr

 

 

## k8s-cluster.yml 수정

$ vi inventory/k1-seungkyua/extra-vars.yml

 

enable_nodelocaldns: false

 

# 신규 설치시에만 세팅

# skydns_server: "{{ kube_service_addresses|ipaddr('net')|ipaddr(10)|ipaddr('address') }}"

 

kube_proxy_mode: ipvs

 

# hostname and hosts file

populate_inventory_to_hosts_file: false

override_system_hostname: false

 

# Helm deployment

helm_enabled: true

 

## copy admin.conf

kubeconfig_localhost: true

kubectl_localhost: true

 

## calico setting

ipip_mode: Never

peer_with_router: true

nat_outgoing: true

global_as_num: "65000"

peers:

  - router_id: "192.168.30.1"

    as: "65000"

 

# calico_ip_auto_method: "interface=eth.*"

# calico_ip_auto_method: "interface=ens6"

calico_ip_auto_method: "can-reach=8.8.8.8"

 

kubeadm_enabled: true

 

docker_insecure_registries:

  - tacorepo:5000

 

dashboard_enabled: true

 

# Local volume provisioner deployment

local_volume_provisioner_enabled: true

 

metrics_server_enabled: true

 

## rbd provisioner deployment

rbd_provisioner_enabled: true

rbd_provisioner_monitors: 192.168.30.23:6789,192.168.30.24:6789,192.168.30.25:6789

rbd_provisioner_pool: kubes

rbd_provisioner_secret: QVFBTmRVVlh5UmZoTlJBQTMyZTh6Qk5uajV1VElrMDJEbWFwWmc9PQ==

rbd_provisioner_user_secret: QVFDdC9CcFlpZ0o3TVJBQTV2eStjbDM5RXNLcFkzQyt0WEVHckE9PQ==

 

 

저의 경우에는 calico 를 활용하여 switch 와 bgp 로 통신하므로 bgp 설정을 넣었습니다.

 

 

 

## k8s 업그레이드 수행

$ ansible-playbook -e @inventory/k1-seungkyua/extra-vars.yml -b -f 30 -i inventory/k1-seungkyua/inventory.ini upgrade-cluster.yml

 

 

 

업그레이드를 돌리면 순차적으로 drain 과 uncordon 을 수행하는데 중간에 에러가 날 경우에는 kubelet 을 업그레이드 이전 버전으로 돌려놓아야 합니다.

 

예를 들어, master02 를 업그레이드 하다가 에러가 나면 아래의 작업을 수행해 줘야 합니다.

 

1. 에러가 나도 kubelet 의 버전은 올라가므로 kubelet 버전을 업그레이드 이전으로 다운그레이드 해야 합니다. 쉬운 방법은 다른 노드에 있는 kubelet 을 복사해서 kubelet 을 restart 해야 합니다.

systemctl restart kubelet

 

 

2. schedule 이 disabled 되어 있을 수 있으니 uncordon 해줘야 합니다.

kubectl uncordon k1-master02

  

 

 

 

 

## 업그레이드 시 에러 날 경우

PodDisruptionBudget 을 확인해야 함

istio 의 MIN AVAILABLE 은 전부 0 으로 세팅

elasticsearch 는 삭제

 

# kubectl get PodDisruptionBudget -A

NAMESPACE      NAME                          MIN AVAILABLE   MAX UNAVAILABLE   ALLOWED DISRUPTIONS   AGE

istio-system   istio-egressgateway           1               N/A               0                     76d

istio-system   istio-galley                  1               N/A               0                     76d

istio-system   istio-ingressgateway          1               N/A               0                     76d

istio-system   istio-pilot                   1               N/A               0                     76d

istio-system   istio-policy                  1               N/A               0                     76d

istio-system   istio-telemetry               1               N/A               0                     76d

logging        elasticsearch-k1-master-pdb   N/A             1                 0                     71d

 

Master의 root 디렉토리 확인

 

/root/.kube/http-cache 디렉토리 삭제

/root/.docker/config 파일 삭제 (도커 로그인정보를 가지고 있어서 docker pull 이 안될 수 있음)

 

coreDNS 가 10.233.0.3 이면 kubeadm 에서 coreDNS 는 10.233.0.10 이어야 한다는 업그레이드 에러 발생

 

kubeadm 명령어에 --print-config 옵션을 붙혀서 미리 한 번 실행하여 이상이 없는지 확인

 

kubeadm upgrade apply -y v1.17.7 --config=/etc/kubernetes/kubeadm-config.yaml --ignore-preflight-errors=all --allow-experimental-upgrades --allow-release-candidate-upgrades --etcd-upgrade=false --certificate-renewal=true --force --v=9 --print-config

 

실행에 이상이 없으면 kubespray 의 roles/kubernetes/master/tasks/kubeadm-upgrade.yml 에 해당 옵션을 추가

 

 

 

 

kubelet upgrade 시에 에러가 발생하였음.

kubelet 버전은 v1.16.3 에서 v1.17.7 로 업그레이드가 되었으나 기존 옵션으로 kubelet 이 start 시에 에러가 남

kubelet --version 으로 v1.17.7 이면 v1.16.3 으로 kubelet 을 다시 복사하고 Kubelet restart

 

 

 

 

 

 

Posted by Kubernetes Korea co-leader seungkyua@gmail.com

댓글을 달아 주세요

  1. 2020.08.26 19:29  댓글주소  수정/삭제  댓글쓰기

    비밀댓글입니다

Istio 에 대한 문의도 있었고 또 모르시는 분들이 계셔서 글을 올립니다.

 

Istio 는 Kubernetes 에만 올릴 수 있고 Control plane 이 여러 pod 로 구성되어 있습니다.

1.4 버전까지는 아래 다이어그램에서 보이듯이 Control 에 해당하는 컴포넌트들이 각각의 프로세스로 실행되었습니다.  

 

하지만 1.5 버전 부터는 (현재는 1.6 버전이 최신입니다) 아래와 같이 New Architecture 로 변경되었습니다.

 

 

 

모든 컴포넌트가 istiod 라는 하나의 프로세스로 합쳐지고 Mixer 가 없어지고 Pilot 이 Mixer 의 기능까지도 함께 수행하는 것으로 되어 있습니다.

 

Istio 에서는 각 서비스를 관리하는 것도 중요하지만 사실 더 중요한 것은 여기 다이어그램에는 표시되지 않은 Ingress traffic 을 처리하는 Gateway 서버입니다. 모든 트래픽을 받아는 주는 관문 역할을 해야 하고, 백엔드의 Envoy Proxy 와도 연계되어야 하기 때문에 Isito 를 도입한다면 중요하게 고려되어야 할 서비스입니다. 

 

Istio 를 설치하는 방법은 아래 두가지 방법으로 하는 것이 편리합니다.

1. Download Istio

https://istio.io/latest/docs/setup/getting-started/

Istio 를 다운받아 istioctl 로 Configure Profile 을 활용하여 설치하는 방법입니다.

 

2. Standalone Operator Install

https://istio.io/latest/docs/setup/install/standalone-operator/

Istio Operator 를 설치하고 이를 기반으로 Istio 를 설치하는 방법입니다.

 

 

Posted by Kubernetes Korea co-leader seungkyua@gmail.com

댓글을 달아 주세요

Kubernetes 를 가르친다고 하면 어떻게 교육을 구성하면 효과적일지 생각해 봤다.

모든 과정이 그렇겠지만 가장 기본적인 내용을 먼저 설명하고 응용, ecosystem 까지 확대하는 순으로 계획해 보았는데, 최소한 5일이 필요한 것 같다.

사실 5일은 부족하지만 그래도 최소한 이정도는 알아야지... 하는 정도가 5일이다.

실습 환경으로 VM (4core, mem 8G, disk 300G)은 4대 (master 1대, node 2대, 스토리지 1대) 가 적절하다.

 

[ Kubernetes 교육 과정 ]

[ 1 day ]
▪ Container 설명 (4H)
  - Container 의 개념 설명
  - Docker, Docker Registry 설치, 실습
  - Dockerfile 작성 실습, 명령어 실습

▪ Kubernetes 설명 (2H)
  - Kubernetes 배경, 아키텍처 설명

▪ Kubernetes 설치 실습 (2H)
  - Kubespray 설명
  - Kubespray 를 활요한 Kubernetes 설치

[ 2 day ]
▪ Kubernetes 활용 (4H)
  - Kubernetes Cli 실습
  - Kubernetes Resource 활용 실습
    - Pod, ReplicaSet, Deployment, StatefulSet, DaemonSet, Job

▪ Kubernetes 네트워크 활용 (4H)
  - Calico 네트워크의 이해
  - Cilium 네트워크의 이해

[ 3 day ]
▪ Kubernetes 고급 활용 (2H)
  - 스토리지 PV (Persistent Volumen) 활용
  - Kubernetes Auto scaling 설치

▪ Helm 설명 (2H)
  - Helm 의 개념, 구조 설명
  - Helm 기본 패키지 생성 실습

▪ DevOps 구축 실습 (4H)
  - Kubernetes 기반 Jenkins 설치
  - Jenkins 를 활용한 Pipeline 구성 실습

[ 4 day ]
▪ Kubernetes Pattern 설명 (4H)
  - Kubernetes 에서 활용될 수 잇는 Pattern 을 설명
    - Init Container, Resource Request/Limit, Scheduling

▪ Kubernetes Programming 실습 (4H)
  - Golang 설명
  - Operator 설명
  - Custom Controller 개발 실습
  - Admission Webhook 설명

[ 5 day ]
▪ Kubernetes Monitoring 실습 (4H)
  - Prometheus / Grafana 설명, 설치, 실습
  - exporter 설명

▪ Kubernetes Logging 실습 (4H)
  - Elastic Search, FluentBit, Kibana 설명, 설치, 실습

 

 

------------------------- 보너스 ----------------------------------


[ 6 day - 한 분야당 2H 보다는 최소 하루가 적절할 듯 ]
▪ Kubernetes Ecosystem 설명 (8H)

  - Cluster-API 설명, 실습
  - Machine Learning Infra - Kubeflow 설명, 실습
  - MSA(Microservice Architecture) - Istio 설명, 실습
  - Continuous Delivery 설명 - ArgoCD 설명, 실습

 

 

Posted by Kubernetes Korea co-leader seungkyua@gmail.com

댓글을 달아 주세요

  1. BlogIcon 레브 다시보기 2020.08.27 14:45  댓글주소  수정/삭제  댓글쓰기

    잘 보고 갑니다...

Kubernetes Upgrade 는 고려해야 할 사항이 많지만 Kubespray 를 활용하면 의외로 간단할 수 도 있다.

Kubespray 는 Kubernetes 설치에 kubeadm 을 활용하기 때문에 업그레이드는 Kubernetes 의 바로 윗단계 마이너버전까지만 가능하다. 예를 들어 지금 Kubernetes 버전이 v1.14.x 이면 v1.16.x 로는 업그레이드를 못한다. v1.16.x 로 업그레이드를 하기 위해서는 v1.15.x 로 업그레이드를 하고, v1.16.x 로 다시 업그레이드를 해야 한다.

 

마침 업그레이드가 필요했고 현재 설치된 Kubernetes 버전이 v1.14.3 이므로 v1.15.6 으로 업그레이드를 먼저 진행하였다.

$ cd kubespray

$ git branch
  master
* release-2.11
  release-2.12
  tag_v2.10.4
  tag_v2.9.0

Kubespray 의 release-2.11 branch 는 Kubernetes Kubernetes v1.15.6 이다. 아래 명령어로 확인할 수 버전을 확인할 수 있다.

kube_version: v1.15.6

$ grep -nr kube_version: .
./docs/upgrades.md:30:And then repeat with v1.4.6 as kube_version:
./inventory/sample/group_vars/k8s-cluster/k8s-cluster.yml:23:kube_version: v1.15.6
./inventory/k1-seungkyua/group_vars/k8s-cluster/k8s-cluster.yml:23:kube_version: v1.15.6
./roles/download/defaults/main.yml:52:kube_version: v1.15.6
./roles/kubespray-defaults/defaults/main.yaml:15:kube_version: v1.15.6
./RELEASE.md:37:  is bound to ``kube_version: 1.4.x``, ``calico_version: 0.22.0``, ``etcd_version: v3.0.6``,
./RELEASE.md:40:  And Kubespray v3.x.x shall be bound to ``kube_version: 2.x.x`` respectively.

먼저 Master 3대를 업그레이드 하여 업그레이드를 순차적으로 하는 것이 좋다. Kubernetes Master 와 Work Node 는 minor 차이가 나더

라도 큰 문제가 생기지 않기 때문에 순차적 검증을 할 수 있다. 물론 kube-apiserver 에서 활성화한 특정 feature 와 resource version 은 사전에 반드시 테스트하여 안전성을 확보한 후 진행해야 한다. 

$ ansible-playbook -e @inventory/k1-seungkyua/extra-vars.yml -b -f 30 -i inventory/k1-seungkyua/inventory.ini upgrade-cluster.yml --limit k1-master01,k1-master02,k1-master03

중요한 것은 --limit 옵션으로 Master 만 업그레이드를 진행한다는 것이다.

Every 2.0s: kubectl get nodes                                                                                                                                           Thu Jan  9 16:15:35 2020

NAME          STATUS   ROLES          AGE    VERSION
k1-master01   Ready    master         323d   v1.15.6
k1-master02   Ready    master         323d   v1.15.6
k1-master03   Ready    master         323d   v1.15.6
k1-node01     Ready    ingress,node   323d   v1.14.3
k1-node02     Ready    node           323d   v1.14.3
k1-node03     Ready    node           322d   v1.14.3
k1-node04     Ready    node           323d   v1.14.3
k1-node05     Ready    node           323d   v1.14.3

 

이제 Worker 를 업그레이드 할 차례인데, Worker 를 업그레이드는 고려해야 할 사항이 있다. 노드를 업그레이드 하기 위해서는 drain 을 하여 Pod 를 eviction 하는데 Kubespray 는 evction 이 완료될 때 까지 기다린다. DaemonSet 은 무시하는 옵션이 있지만 PodDisruptionBudget 은 policy 에 걸리면 pod 가 terminating 상태에서 완료되지 않기 때문에 timeout 으로 업그레이드에 실패하게 된다. 여기서는 elasticsearch 가 문제가 있어 timeout 나서 실패하였다.

# kubectl get PodDisruptionBudget -A
NAMESPACE      NAME                          MIN AVAILABLE   MAX UNAVAILABLE   ALLOWED DISRUPTIONS   AGE
istio-system   istio-egressgateway           1               N/A               0                     76d
istio-system   istio-galley                  1               N/A               0                     76d
istio-system   istio-ingressgateway          1               N/A               0                     76d
istio-system   istio-pilot                   1               N/A               0                     76d
istio-system   istio-policy                  1               N/A               0                     76d
istio-system   istio-telemetry               1               N/A               0                     76d
logging        elasticsearch-k1-master-pdb   N/A             1                 0                     71d

elasticsearch 문제를 해결하고 다시 k1-node01 이라는 Worker 노드  1대만 업그레이드를 진행한다.

$ ansible-playbook -e @inventory/k1-seungkyua/extra-vars.yml -b -f 30 -i inventory/k1-seungkyua/inventory.ini upgrade-cluster.yml --limit k1-node01

문제없이 업그레이드가 완료되었다.

Every 2.0s: kubectl get nodes                                                                                                                                           Thu Jan  9 16:27:17 2020

NAME          STATUS   ROLES          AGE    VERSION
k1-master01   Ready    master         323d   v1.15.6
k1-master02   Ready    master         323d   v1.15.6
k1-master03   Ready    master         323d   v1.15.6
k1-node01     Ready    ingress,node   323d   v1.15.6
k1-node02     Ready    node           323d   v1.14.3
k1-node03     Ready    node           322d   v1.14.3
k1-node04     Ready    node           323d   v1.14.3
k1-node05     Ready    node           323d   v1.14.3

이제 나머지 노드를 모드 업그레이드를 하면 된다. Kubespray 는 한대씩 순차적으로 업그레이드를 하기 때문에 전체 서비스에는 영향이 없다. (서비스를 여러 pod 로 load balancing 했을 경우에)

 

Posted by Kubernetes Korea co-leader seungkyua@gmail.com

댓글을 달아 주세요

이제는 Kubenretes 가 많이 사용되고 성숙해진 것 같다. KubeCon US 2019 에서도 키노트에 Security 를 강조한 것을 보면 잘 알 수가 있는데, 일반적으로 보안을 강조하기 시작하면 이미 해당 field 는 많이 성숙한 단계라고 봐도 무관하다.

 

그래서 Kubernetes 보안에 관심을 갖고 관련 내용을 찾아봤다. 뭐 별로 내용이 많지는 않지만...

 

1. CIS (Center for Internet Security)

CIS

Kubernetes 관련하여 Benchmark 자료가 나와 있는 사이트. 현재 Kubernetes 버전은 1.15 까지 나와 있다.

 

물론 Linux, Windows 와 같은 OS 부터 Apache, Nginx 와 같은 웹서버에 대한 benchmark 자료도 다운 받을 수 있다. 보안을 다루는 곳이라면 다 알듯...

 

 

2. OPA (Open Policy Agent)

https://github.com/open-policy-agent/gatekeeper

 

open-policy-agent/gatekeeper

Gatekeeper - Policy Controller for Kubernetes. Contribute to open-policy-agent/gatekeeper development by creating an account on GitHub.

github.com

CNCF 프로젝트 중에 하나로, RBAC 으로 권한에 제한을 두었다고 하더라도 해당 권한의 사용자 컨테이너가 탈취당한다면 컨테이너 안에서 Docker 명령이나 Kubectl 명령으로 새로운 자원을 띄우는 것이 가능하다. 이런 비정상 상황에서 자원 생성을 막을 수 있는 것이 OPA의 gatekeeper 이다.

 

 

3. Clair

https://coreos.com/clair/docs/latest/

 

CoreOS

Clair is an open source project for the static analysis of vulnerabilities in appc and docker containers. Read our Clair documentation for easy deployment.

coreos.com

CoreOS 에서 만든 docker 컨테이너의 취약점을 정적으로 분석해주는 오픈소스 프로젝트. 내부적으로 Docker Image Registry 를 사용하고 있다면 사용을 고려해 봐야 한다.

 

 

 

Posted by Kubernetes Korea co-leader seungkyua@gmail.com

댓글을 달아 주세요

  1. BlogIcon 영화다시보기 2020.08.25 11:00  댓글주소  수정/삭제  댓글쓰기

    잘 보고 갑니다...

Kubernetes 의 모든 metadata 는 etcd 에 저장됩니다. etcd 를 안정적으로 가져가기 위해 3 node 로 cluster 를 구성하는 방법을 사용합니다. 대부분의 문서는 일반적으로 etcd 를 백업 / 복구로 설명하고 있는데, 그 보다 서버 fault 가 나서 etcd 를 1 node 나 2 node 로 임시 운영해야 할 경우에 대해서 설명하고자 합니다.

 

[ etcd 노드 리스트 ]

k2-master01 : etcd1

k2-master02 : etcd2

k2-master03 : etcd3

 

먼저 etcdctl 명령어를 사용하기 쉽게 alias 로 다음과 같이 등록을 해줍니다. 각 노드 마다 endpoint ip 와 인증서 파일은 이름을 적절히 변경해 주어야 합니다.

# vi ~/.bash_aliases

alias etcdctl="export ETCDCTL_API=3; etcdctl --endpoints=[192.168.30.151:2379] --cacert=\"/etc/ssl/etcd/ssl/ca.pem\" --cert=\"/etc/ssl/etcd/ssl/admin-k2-master01.pem\" --key=\"/etc/ssl/etcd/ssl/admin-k2-master01-key.pem\" "


# . ~/.bash_aliases

 

멤버 조회를 하면 다음과 같이 3개 노드가 정상적으로 나타납니다.

# etcdctl --write-out=table member list
+------------------+---------+-------+-----------------------------+-----------------------------+
|        ID        | STATUS  | NAME  |         PEER ADDRS          |        CLIENT ADDRS         |
+------------------+---------+-------+-----------------------------+-----------------------------+
| 683a3374b573e7c7 | started | etcd1 | https://192.168.30.151:2380 | https://192.168.30.151:2379 |
| 6f89416652d7e034 | started | etcd2 | https://192.168.30.152:2380 | https://192.168.30.152:2379 |
| d9c4159e72350017 | started | etcd3 | https://192.168.30.153:2380 | https://192.168.30.153:2379 |
+------------------+---------+-------+-----------------------------+-----------------------------+

 

모든 노드의 etcd 를 stop 하여 3대 모두 장애상황으로 만듭니다.

# systemctl stop etcd

 

3대 노드의 etcd 가 모두 장애로 다운되었고, 빠른 서비스를 위해 etcd1 만 띄운다고 하면, etcd db 에 이미 기존의 3대 cluster member 를 인식하고 있기 때문에 etcd1 만 실행시키는 것을 실패하게 됩니다. 이 때는 기존의 db  (백업 db 가 아닌 운영되고 있었던 db) 를 가지고 restore 를 하여 member 정보를 새롭게 update 할 수 있습니다. 그리고 snapshot 으로 백업된 db 정보가 아니므로 hash check 도 skip 을 해야 합니다.  

 

k2-master01 노드에서 작업

먼저, db 를 복사해 옵니다. (etcd 의 data dir 는 /var/lib/etcd 라고 가정합니다.) 그리고 /var/lib/etcd 디렉토리는 삭제합니다.

# mkdir -p ~/etcd-backup
# cp /var/lib/etcd/member/snap/db ~/etcd-backup/current.db

# rm -rf /var/lib/etcd/

 

복사한 db 를 사용하여 restore 를 하면서, initial-cluster 값으로 member 정보를 덮어씁니다.

# etcdctl snapshot restore ~/etcd-backup/current.db \
--data-dir=/var/lib/etcd \
--initial-advertise-peer-urls=https://192.168.30.151:2380 \
--initial-cluster=etcd1=https://192.168.30.151:2380 \
--initial-cluster-token=k8s_etcd \
--name=etcd1 \
--skip-hash-check

 

새롭게 cluster 를 생성하는 방식으로 etcd1 만 실행하기 위해 옵션 값 중에 ETCD_INITIAL_CLUSTER_STATE=new 와 ETCD_INITIAL_CLUSTER=etcd1=https://192.168.30.151:2380 으로 변경합니다.

# vi /etc/etcd.env

# Environment file for etcd v3.2.26
ETCD_DATA_DIR=/var/lib/etcd
ETCD_ADVERTISE_CLIENT_URLS=https://192.168.30.151:2379
ETCD_INITIAL_ADVERTISE_PEER_URLS=https://192.168.30.151:2380
#ETCD_INITIAL_CLUSTER_STATE=existing
ETCD_INITIAL_CLUSTER_STATE=existing
ETCD_METRICS=basic
ETCD_LISTEN_CLIENT_URLS=https://192.168.30.151:2379,https://127.0.0.1:2379
ETCD_ELECTION_TIMEOUT=5000
ETCD_HEARTBEAT_INTERVAL=250
ETCD_INITIAL_CLUSTER_TOKEN=k8s_etcd
ETCD_LISTEN_PEER_URLS=https://192.168.30.151:2380
ETCD_NAME=etcd1
ETCD_PROXY=off
ETCD_INITIAL_CLUSTER=etcd1=https://192.168.30.151:2380,etcd2=https://192.168.30.152:2380,etcd3=https://192.168.30.153:2380
ETCD_AUTO_COMPACTION_RETENTION=8
ETCD_SNAPSHOT_COUNT=10000

# TLS settings
ETCD_TRUSTED_CA_FILE=/etc/ssl/etcd/ssl/ca.pem
ETCD_CERT_FILE=/etc/ssl/etcd/ssl/member-k2-master01.pem
ETCD_KEY_FILE=/etc/ssl/etcd/ssl/member-k2-master01-key.pem
ETCD_CLIENT_CERT_AUTH=true

ETCD_PEER_TRUSTED_CA_FILE=/etc/ssl/etcd/ssl/ca.pem
ETCD_PEER_CERT_FILE=/etc/ssl/etcd/ssl/member-k2-master01.pem
ETCD_PEER_KEY_FILE=/etc/ssl/etcd/ssl/member-k2-master01-key.pem
ETCD_PEER_CLIENT_CERT_AUTH=True

 

이제 etcd 를 실행하면 이전 데이터를 가지고 1대의 노드로 실행시킬 수 있습니다.

# systemctl start etcd

 

멤버 조회를 해보면 자신만 나오는 것을 알 수 있습니다.

# etcdctl --write-out=table member list
+------------------+---------+-------+-----------------------------+-----------------------------+
|        ID        | STATUS  | NAME  |         PEER ADDRS          |        CLIENT ADDRS         |
+------------------+---------+-------+-----------------------------+-----------------------------+
| 683a3374b573e7c7 | started | etcd1 | https://192.168.30.151:2380 | https://192.168.30.151:2379 |
+------------------+---------+-------+-----------------------------+-----------------------------+

 

etcd 3 node cluster 원상 복구

k2-master01 서버에서 작업

etcd cluster 를 다시 3 node 로 만들기 위해 etcd2 member 를 add 합니다.

# etcdctl member add etcd2 --peer-urls=https://192.168.30.152:2380
Member d8f69cbfe4c8a34f added to cluster a6552752c1542947

ETCD_NAME="etcd2"
ETCD_INITIAL_CLUSTER="etcd1=https://192.168.30.151:2380,etcd2=https://192.168.30.152:2380"
ETCD_INITIAL_CLUSTER_STATE="existing"

 

k2-master02 서버에서 작업

etcd.env 에서 initial cluster 값에 자기 자신인 etcd2 를 추가합니다. initial cluster state 는 existing 으로 그대로 진행합니다.

# vi /etc/etcd.env

ETCD_INITIAL_CLUSTER=etcd1=https://192.168.30.151:2380,etcd2=https://192.168.30.152:2380

etcd2 의  data dir 를 삭제하고 etcd2 ㅇ를 실행합니다.

# rm -rf /var/lib/etcd/
# systemctl start etcd

member 조회를 하면 정상적으로 etcd2 가 추가된 것을 알 수 있습니다.

# etcdctl --write-out=table member list
+------------------+---------+-------+-----------------------------+-----------------------------+
|        ID        | STATUS  | NAME  |         PEER ADDRS          |        CLIENT ADDRS         |
+------------------+---------+-------+-----------------------------+-----------------------------+
| 683a3374b573e7c7 | started | etcd1 | https://192.168.30.151:2380 | https://192.168.30.151:2379 |
| d8f69cbfe4c8a34f | started | etcd2 | https://192.168.30.152:2380 | https://192.168.30.152:2379 |
+------------------+---------+-------+-----------------------------+-----------------------------+

 

k2-master01 서버에서 작업

etcd3 member 를 add 합니다.

# etcdctl member add etcd3 --peer-urls=https://192.168.30.153:2380
Member 63f37d54154a6e23 added to cluster a6552752c1542947

ETCD_NAME="etcd3"
ETCD_INITIAL_CLUSTER="etcd3=https://192.168.30.153:2380,etcd1=https://192.168.30.151:2380,etcd2=https://192.168.30.152:2380"
ETCD_INITIAL_CLUSTER_STATE="existing"

 

k2-master03 서버에서 작업

etcd3 의 data dir 삭제 및 etcd3 를 start 합니다.

# rm -rf /var/lib/etcd
# systemctl start etcd

정상적으로 member 가 추가되었음을 알 수 있습니다.

# etcdctl --write-out=table member list
+------------------+---------+-------+-----------------------------+-----------------------------+
|        ID        | STATUS  | NAME  |         PEER ADDRS          |        CLIENT ADDRS         |
+------------------+---------+-------+-----------------------------+-----------------------------+
| 63f37d54154a6e23 | started | etcd3 | https://192.168.30.153:2380 | https://192.168.30.153:2379 |
| 683a3374b573e7c7 | started | etcd1 | https://192.168.30.151:2380 | https://192.168.30.151:2379 |
| d8f69cbfe4c8a34f | started | etcd2 | https://192.168.30.152:2380 | https://192.168.30.152:2379 |
+------------------+---------+-------+-----------------------------+-----------------------------+

 

 

마지막으로 설정을 변경해야 할 것이 있습니다. 언제든지 etcd 는 restart 를 할 수 있으므로 etcd1 과 etcd2 의 initial cluster state 를 existing 으로 변경하고 initial cluster 의 멤버를 3대로 모두 지정해야 합니다.

 

k2-master02 서버에서 작업

etcd2 옵션의 initial cluster 값에 etcd3 를 포함

# vi /etc/etcd.env

ETCD_INITIAL_CLUSTER=etcd1=https://192.168.30.151:2380,etcd2=https://192.168.30.152:2380,etcd3=https://192.168.30.153:2380

 

k2-master01 서버에서 작업

etcd1  옵션의 initial cluster state 를 existing 으로 변경하고 initial cluster 값에 etcd2 와 etcd3 를 포함

# vi /etc/etcd.env

ETCD_INITIAL_CLUSTER_STATE=existing
ETCD_INITIAL_CLUSTER=etcd1=https://192.168.30.151:2380,etcd2=https://192.168.30.152:2380,etcd3=https://192.168.30.153:2380

 

 

Posted by Kubernetes Korea co-leader seungkyua@gmail.com

댓글을 달아 주세요

Ingress Controller 를 사용하여 같은 도메인에서 subpath 로 웹서비스를 분리하는 방법은 각 서비스마다 Ingress 를 만들고, '/' path 는 무조건 포함시키는 방법입니다. 한가지 단점은 root path '/' 는 처음 만든 Ingress 가 먼저 선점하게 됩니다.

 

물론 이 방법은 '/' 가 경로가 반드시 필요한 서비스가 2개 이상이면 적용할 수 없지만 그런 경우는 없다고 가정합니다.

 

예를 들어 Jupyterlab 은 '/' 경로를 반드시 필요로 합니다. '/jupyter' 를 호출할 때 jupyterlab 이 호출되게 Ingress 의 subpath 를 지정하려면 다음과 같이 작성하면 됩니다.

 

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /
  name: jupyterlab
  namespace: jupyterlab
spec:
  rules:
  - host: jupyterlab.myserver
    http:
      paths:
      - backend:
          serviceName: jupyterlab
          servicePort: 80
        path: /jupyter
  - host: jupyterlab.myserver
    http:
      paths:
      - backend:
          serviceName: jupyterlab
          servicePort: 80
        path: /

이렇게 하면 'http://jupyterlab.myserver/jupyter' 가 호출되거나 'http://jupyterlab.myserver/' 가 호출되어도 jupyterlab 이 잘 연결됩니다.

 

여기에 '/echoserver' 를 subpath 로 연결되게 추가하고 싶으면 새로운 Ingress 를 만들면 됩니다.

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /
  name: echoserver
  namespace: jupyterlab
spec:
  rules:
  - host: jupyterlab.myserver
    http:
      paths:
      - backend:
          serviceName: clusterip
          servicePort: 80
        path: /echoserver
  - host: jupyterlab.myserver
    http:
      paths:
      - backend:
          serviceName: clusterip
          servicePort: 80
        path: /

여기서 두번째에 들어가 '/' 는 소용이 없습니다. Nginx 에서는 처음 입력된 순서에 의해서 location 이 결정되기 때문에 'http://jupyterlab.myserver/' 를 호출하면 첫번째 생성한 jupyterlab ingress 가 적용되기 때문입니다. 

 

 

Posted by Kubernetes Korea co-leader seungkyua@gmail.com

댓글을 달아 주세요