AWS 기반으로 CodeCommit 과 연동하여 개발을 하다보면 Windows 기반의 Eclipse 연동을 주로 사용합니다.

AWS 에서 IntelliJ 가 아닌 Eclipse plugin 을 사용하라고 가이드 하는 것은 아마도 Eclipse 가 오픈소스 IDE 툴 이기 때문에 aws plugin 을 만들어서 배포하기데 적절하기 때문이 아닌가 하고 생각이 드네요.

저는 Mac 기반의 Eclipse 를 사용하는데 AWS CodeCommit 과 연동시키는데 몇시간을 고생해서 해결한 내용을 설명하고자 합니다.

Eclipse 를 설치하기 전에 먼저 JDK 가 설치되어야 하는데, 이전 글에서 Mac 에 JDK 를 설치하는 것은 설명을 드렸습니다.

다음으로 Eclipse 설치는 그냥 Applications 아이콘에 복사만 하면 되므로 Eclipse 설치는 생략...

 

Eclipse 에서 AWS toolkt 설치는 "메뉴 >> Help >> Install New Software..." 창을 띄우고 "Work with" 레이블이 있는 Text 상자에  "https://aws.amazon.com/eclipse/site.xml" 를 입력해서 software 를 설치하면 됩니다.

 

 

AWS CodeCommit 을 사용하기 위해서는 "IAM >> Users" 의 Security Credentials 탭에서 "HTTPS Git credentials for AWS CodeCommit" 항목에 사용자를 등록하면 사용할 수 있습니다.

 

 

그리고 AWS CodeStar 에서 Project 를 하나 만들면, CodeCommit Repository 가 생성이 되고,  이 Project 의 Team 메뉴에 위의 IAM User 를 할당해 주면 해당 User 가 CodeCommit 을 사용할 수 있습니다. 

 

이제 Eclipse 의 주황색 아이콘을 클릭해서 CodeCommit 의 repository 로 부터 소스를 받아오겠습니다.

 

AWS Access Key ID, Secret Access Key 를 넣고 region 을 선택합니다. 그리고 CodeCommit 의 git id 와 패스워드를 입력하면 소스를 다운받을 수 있습니다.

 

하지만 다운을 받다가 에러가 발생하면서 실패하게 됩니다.

이 부분에서 고생을 많이 했었는데..

 

1. 처음에는 Oracle Java 에서 나는 문제로 오해해서 Mac 에 OpenJDK 를 설치했습니다. 그리고 Eclipse 를 띄울 때 OpenJDK 를 사용할 수 있게 수정했습니다.

그래도 똑같은 에러가 발생했습니다.

2. 그래서 JGit 의 버그로 생각하고 5.9 버전에서 낮은 버전으로 다시 설치했습니다.

그래도 에러가 발생.

3. IAM User 에서 https git credential 을 지우고 다시 생성하면 된다고 구글리에 나와 있어서 다시 했지만 또 에러.

마지막으로 아래 부분을 적용했더니 해결.

4. Eclipse "Preferences > General > Security > Secure Storage" 에서 OS X keystore 연동 체크박스를 해제

 

결국은 Mac 에서 keychain 연동할 때 eclipse 의 security storage 와의 이슈 때문이었습니다.

별거 아니지만 계속 고생할 수 있는 분들이 있을 거 같아 기록으로 남겨 봅니다. ^^

 

 

 

 

 

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

댓글을 달아 주세요

어제 AWS VPC 네트워크의 개념에 대해서 배워서 정리해 봤습니다.

저는 OpenStack 을 오랫동안 해왔기 때문에 OpenStack 의 Neutron 로 비교하면 이해가 더 쉽게 되더라고요.

 

 

먼저 네트워크 대역을 만들기 위해서는 VPC 가 필요합니다. virtual 하게 만드는 것이기 때문에 10.0.0.0/16 과 같이 사설망 대역을 사용합니다.

그리고 외부와의 통신을 위해서는 Internet gateway (IGW)를 생성합니다. 이것은 software gateway 라고 생각이 들고 여기까지는 VPC 와 상관이 없습니다. 그래서 이해하기 쉽게 IGW 를 VPC 바깥에 그렸습니다.

IGW 를 VPC 와 연결 (associate) 하는 순간에 port 가 생성되어 연결될 것으로 보입니다.

 

VPC 내에는 subnet 을 만들어 Network 대역을 다시 나눌 수 있는데 subent 은 10.0.0.0/24 처럼 VPC 대역 내여야 하고, 하나의 subent 은 AZ 의 하나에만 할당될 수 있습니다. AZ 내에 하나만 할 당 할 수 있는 이유는 EC2 VM 을 만들면 VPC 내의 Subnet 을 선택하고, VM에 ip 를 할당하면서 해당 IP 에 대해서 s/w 적으로 연결이 될텐데 여러 AZ 에 대역이 펼쳐져 있으면 통신이 꼬일 수 밖에 없습니다.

그러므로 실제로 중요한 것은 VPC 라기 보다는 Subnet 입니다. Subnet 의 정보를 가지고 다 처리를 하는데 다만 통합적으로 관리할려고 VPC 라는 개념을 가져온 것 뿐입니다. 

 

Subnet 은 라우팅을 잡아야 하는데, 내부적으로는 VM 을 관리하는 Baremetal Host 서버에 라우팅을 세팅하기 위한 방법이 필요합니다. (혹은 Baremetal 에 떠 있는 software network switch 에서 라우팅을 세팅)

그래서 라우팅 테이블을 만들고 Subnet 에 연결(assocation) 해주면 그 라우팅 정보를 가지고 있다가 VM 이 생성될 때 세팅을 해줄 수 있습니다.

 

정리해보면 다음과 같습니다.

1. IGW 는 VPC 에 attach 하는 부분이 필요하다. (router 에서 인터넷으로 가는 GW port 를 연결하는 작업)

2. Route table 을 Subnet 에 association 하는 부분이 필요하다 ( VM 이 생성될 때 통신될 수 있도록 라우팅을 세팅해야 하므로 해당 정보를 이용)

 

AWS 가 내부적으로 어떻게 구성되어 있는 지는 모르겠습니다. 하지만 OpenStack Neutron 을 보면 저런 방법을 사용하고 있기 때문에 아마도 동작 방식은 비슷하지 않을까 생각합니다.

 

  

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 교육 과정(안)을 적어본 김에 OpenStack 과정도 생각해 봤다.

 

[ OpenStack 교육 과정 ]

[ 1 day ]
OpenStack 소개 (2H)
 - OpenStack 배경, 구성요소, 아키텍처, 기능 등을 설명
OpenStack 설치 실습 (4H)
 - OpenStack 기본 설정 설치 (cinder 제외, tenant network 로 설정)
OpenStack Cli 실습 (2H)
 - OpenStack Cli 활용 실습

[ 2 day ]
OpenStack Identity 관리 (1H)
 - Keystone 설정, 기능 설명과 명령어를 실습
OpenStack Image 관리 (4H)
 - Glance 설정, 기능 설명
 - Diskimage-builder 를 활용한 이미지 생성, cloud-init 활용
 - 명령어 실습
Ceph 스토리지 관리 (4H)
 - Ceph 스토리지 기본 설명 및 설치 실습
 - Cinder 설치, 설정, 기능 설명
 - 명령어 실습

[ 3 day ]
OpenStack 네트워크 관리 (8H)
 - Neutron 기능 설명
 - provider network 설정, 기능 설명
 - tenant network 설정, 기능 설명
 - OVN (Open Vistual Network) 설명

[ 4 day ]
OpenStack Compute 관리 (4H)
 - Nova Compute 설정, 기능 설명
 - Live migration, evacuation, 노드 활성화,비활성화 실습
OpenStack 종합 실습 (4H)
 - 로그를 통한 문제 해결 방법
 - Custum image 생성, 등록, VM 인스턴스 생성 등의 모든 기능을 실습

 

 

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

댓글을 달아 주세요