반응형

 

 


테스트는 나중에 하고, 오늘은 아래 블로그를 정독하고 이해만 하기로 함~~~~

 

https://jerryljh.tistory.com/40

 

Kubernetes Snapshot 백업/복구

Kube 환경에서도 기존 storage 벤더에서 제공하는 snapshot 기능을 사용 가능합니다. kube 환경답게 snapshot도 manifest YAML 파일 형태를 사용합니다. 그럼, 테스트 내역 공유합니다. Test 내역 snapshot 지원 sto

jerryljh.tistory.com

 

반응형

 



설치 및 테스트한 날짜: 2023년 4월 12일
Harbor version: v2.7.0

 

아래 문서에 준비 작업, 설정, 설치 과정이 자세히 설명되어 있다. 세부적인 설정이 필요하다면 아래 문서를 읽어보는 것이 좋다.

 

https://goharbor.io/docs/2.7.0/install-config/

 

Harbor – Harbor Installation and Configuration

Harbor Installation and Configuration

goharbor.io

 

 

1) 사전 준비 작업

아래 Web docs에 Harbor 운영에 필요한 HW 스펙 및 Software, Network port 정보가 있다.

 

https://goharbor.io/docs/2.7.0/install-config/installation-prereqs/

 

특별한 내용이 없으니까, 간단하게 읽고 패쑤~

 

 

2) Harbor Installer 다운로드 받기

아래 Web docs에 Harbor installer를 다운로드할 수 있는 절차가 설명되어 있다.

특별한 내용이 없으니까, 설명되어 있는 명령을 따라서 수행하면 된다.

 

  - 다운로드에 대한 설명 : https://goharbor.io/docs/2.7.0/install-config/download-installer/

  - 설치 파일 저장소:  https://github.com/goharbor/harbor/releases/tag/v2.7.0  (이 페이지의 제일 밑에 있는 링크를 사용)

  - 실제 다운로드한 파일: https://github.com/goharbor/harbor/releases/download/v2.7.0/harbor-offline-installer-v2.7.0.tgz

 

나는 여러 설치 파일 중에서 'harbor-offline-installer-v2.7.0.tgz' 파일을 다운로드 받았다.

그리고 이 tgz 압축 파일을 풀어준다.  (파일을 설정하고 실행하는 것은 뒤에서 다시 설명함)

 

3) Harbor 서버에 HTTPS Access하기 위한 인증서 만들기

OpenSSL 명령 도구를 잘 사용하는 사람이라면, 아래 Web docs의 예제 명령어를 조금 수정해서 수행하면 된다.

그런데 SSL 지식이 없거나 OpenSSL 명령 도구가 생소한 사람이라면, SSL을 공부하고 아래 Web docs 예제를 따라가는 것이 좋다.

 

https://goharbor.io/docs/2.7.0/install-config/configure-https/

 

내 경우, 위 문서의 예제 명령에서 "yourdomain.com" 부분만 실제 나의 internet domain name으로 변경하고 인증서를 만들었다.

 

 

4) 설정 파일 harbor.yaml 작성하기

위에서 다운로드한 'harbor-offline-installer-v2.7.0.tgz' 파일에 harbor.yml.tmpl 파일이 있다.

이 설정 파일을 내 상황에 맞게 편집하면 되는데, 솔직히 항목이 많고 설명을 읽어도 아리송한 부분이 있다.

내 경우는 전체 설정 항목 중에서 아래 예시와 같이 몇 개만 수정했다.

 

##
## 설정 Template 파일을 복사
##

$  cp  harbor.yml.tmpl  harbor.yml



##
## 설정 파일을 편집하기
##

$  vi  harbor.yml

... 중간 생략 ...

hostname: registry.sejong-world.kr

... 중간 생략 ...

https:
  port: 443
  certificate: /data/cert/sejong-world.kr.crt
  private_key: /data/cert/sejong-world.kr.key

harbor_admin_password: MyNewPass56789


$

 

 

 

5) 설치 Script 실행하기

아래 Web docs에 설명이 잘 되어 있어서 따라 하기만 해도 잘 설치된다.

 

https://goharbor.io/docs/2.7.0/install-config/run-installer-script/

 

단, 설치하는 방식에 따라 여러 옵션을 사용할 수 있는데 나는 Chart repository 서비스도 사용할 거라서

아래와 같이  --with-chartmuseum 옵션을 추가했다.

이 옵션으로 설치하면, container image registry와 chart repository 서비스를 모두 사용할 수 있다.

 

$ sudo ./install.sh --with-chartmuseum

 

 

위 옵션을 지정한 것 외에는 나머지 모든 설치 및 기동 종료 절차는 Web docs와 완전히 동일하게 수행했다.

문서의 설명이 간단했고, 따라만 해도 에러없이 설치가 술술 잘 되어서 부연 설명할 부분이 없다.

 

##
## Harbor 서버 종료하기  
##  (옵션 '-v'는 데이터 볼륨을 삭제하라는 뜻)
##

$  docker compose down -v


##
## Harbor 서버 시작하기 
##  (옵션 '-d'는 백그라운드에서 데몬 프로세스로 구동하라는 뜻)
##
$ docker compose up -d

 

 

 

 

 

 

 


 

반응형

 


 


설정 및 테스트한 날짜:  2023년 2월 7일

 

Harbor Registry  같은 private container image registry에 kubernetes가 접근하려면 kubernetes의 secret 리소스를 생성해줘야 한다.

kubernetes에 image registry의 credential(자격 증명)을 어떻게 등록하는지 알아보자~

 

 


설정에 관한 자세한 설명을 보고 싶다면, 아래 문서를 참고.
  참고 문서:   Private registry에서 image 받아오기

 

 

프라이빗 레지스트리에서 이미지 받아오기

이 페이지는 프라이빗 컨테이너 레지스트리나 리포지터리로부터 이미지를 받아오기 위해 시크릿(Secret)을 사용하는 파드를 생성하는 방법을 보여준다. 현재 많은 곳에서 프라이빗 레지스트리가

kubernetes.io

 

 

Harbor registry에 접근할 수 있는 credential을 등록하기 위해 아래의 예제를 따라서 실행한다. 

## regcred 라는 이름의 secret 리소스를 생성한다.

$  kubectl create secret docker-registry regcred --docker-server=registry.sejong.cluster --docker-username=myusername --docker-password=mypassword

## 위에서 생성한 regcred secret 리소스 내용을 확인한다.

$  kubectl get secret regcred --output=yaml

apiVersion: v1
kind: Secret
metadata:
  ...
  name: regcred
  ...
data:
  .dockerconfigjson: eyJodHRwczovL2luZGV4L ... J0QUl6RTIifX0=
type: kubernetes.io/dockerconfigjson

$

## 참고 정보:
##   - .dockerconfigjson 필드는 registry 자격 증명 값의 base64 인코딩한 결과이다.
##   - .dockerconfigjson 필드의 값을 눈으로 볼 수 있도록 base64 decoding한다. (아래와 같이)

$ kubectl get secret regcred --output="jsonpath={.data.\.dockerconfigjson}" | base64 --decode

{"auths":{"registry.sejong.cluster":{"username":"myusername","password":"mypassword","auth":"c3R...zE2"}}}

$

## 위 출력 내용 중에서 'auth' 값을 아래와 같이 base64 decoding한다.

$  echo "c3R...zE2" | base64 --decode

myusername:mypassword

$

 

Kubernetes master node, worker node에 Insecure registry를 등록한다.

만약, 10개의 node가 있다면 10개 모두 동일하게 작업해줘야 한다. (아~  귀찮아 ㅠㅠ)

참고로, OKD 또는 Red Hat OCP를 사용한다면 아래처럼 kubernetes node에 직접 접속해서 수작업으로 설정하지 않아도 된다.
$  vi /etc/crio/crio.conf

...

insecure_registries = [
"registry.sejong.cluster"
]

...

$  systemctl restart crio

$  systemctl status crio

 

 

설정 작업이 끝났으면, 테스트~

 

아래와 같은 예제 Pod를 구동하여 Image pulling이 잘 되는지 확인한다.

 

 

$  cat my-pod-example.yaml

apiVersion: v1
kind: Pod
metadata:
  name: almighty
  labels:
    app: almighty
spec:
  terminationGracePeriodSeconds: 3
  containers:
  - name: almighty
    image: registry.sejong.cluster/scope/almighty:0.2.4
       
$   kubectl apply -f my-pod-example.yaml

pod/almighty created

$  kubectl get pod

NAME           READY   STATUS    RESTARTS   AGE
pod/almighty   1/1     Running   0          3s

$

 

Great !!!  잘 동작한다.

 

 


 

블로그 작성자: sejong.jeonjo@gmail.com

 

반응형

Amazon EKS, Azure AKS, Google GKE 등과 비슷하게 Oracle OKE에서도 Network LB가 제공된다.

 

Managed Kubernetes를 사용할 때 항상 등장하는 Load Balancer와 Network Load Balancer가 비슷하면서 약간 다른데,

Oracle Cloud Infrastructure의 User Manual에는 아래와 같이 설정하고 있다.

 

 

Load Balancer

Oracle OKE - Load Balancer

  A Load Balancer improves resource utilization, facilitates scaling, and helps ensure high availability. You can configure multiple load balancing policies and application-specific health checks to ensure that the load balancer directs traffic only to healthy instances. Includes: advanced proxy features such as layer-7 routing and SSL termination.

그림에서 묘사한 것처럼

  • HTTP
  • HTTPS
  • TCP

프로토콜을 사용하는 Backend 서비스만 지원한다. 

따라서 UDP나 Dedicated Protocol을 사용하는 Backend 서비스가 있는 경우에 이 LB를 사용할 수 없다. ㅠㅠ

 

Network Load Balancer (일명, NLB)

Oracle OKE - Network Load Balancer (NLB)

A Network Load Balancer is a non-proxy layer-4 load balancing solution. It offers a scalable VIP to the customer and additionally provides the benefits of flow high availability, low latency, and source IP and port preservation.
Includes: layer-4 pass-through load balancing and client header preservation.

그림에서 묘사한 것처럼

  • TCP
  • UDP                                             # <-- 이것이 LB와 NLB가 다른 부분이다. 
  • 기타... 아무거나 다 (Any ~~~)      # <-- 이것이 LB와 NLB가 다른 부분이다.  

프로토콜을 사용하는 Backend 서비스를 지원한다. 

그런데 Oracle Cloud Infra에서는 이 NLB(Network LB)는 3개까지만 사용하도록 제한하고 있다.

OCI Web Console에서는 이 NLB Max Limit을 설정하는 메뉴가 안 보이는데, 아마 Oracle에 직접 전화해서 NLB 개수를 Upgrade해야 하는 것 같다. (아직, 확실하진 않고... 내일 Oracle에 한번 전화해서 물어봐야겠다..)

반응형

Public Cloud의 Kubernetes(예: AWS AKS, Azure AKS, Oracle OKE 등)을 사용하다보면,

Public Network에서 들어오는 UDP 트래픽을 Network LB(NLB)가 처리하지 못하는 것처럼 보일 때가 있다.

 

예를 들어 아래와 같은 Service Manifest를 적용했다고 가정해보자.

 

apiVersion: v1
kind: Service
metadata:
  name: almighty
  annotations:
    oci.oraclecloud.com/load-balancer-type: "nlb"  # <- 이 내용을 추가해야 한다.
spec:
  selector:
    app: almighty
  ports:
    - name: myweb
      protocol: TCP
      port: 8080
      targetPort: 8080
    - name: yourweb
      protocol: TCP
      port: 80
      targetPort: 80
    - name: myudp
      protocol: UDP       # <- 테스트를 위해 UDP를 추가한다.
      port: 9090
      targetPort: 9090
  type: LoadBalancer      # <- Service Type을 LoadBalancer로 설정한다.

 

위 Service Manifest를 적용하면, External-IP 항목이 Public IP 값으로 설정되지만 실제로 Pod로 UDP 트래픽이 전달되지 못하는 현상이 생길 것이다.

 

왜 이런 문제가 생길까?

 

Public Network에서 유입되는 UDP 트래픽이 Pod에 전달되지 못하는 정확한 원인은 아래와 같다.

Public Cloud Service 제공사가 제공하는 NLB(Network Load Balancer)는 제대로 UDP 트래픽을 처리한 것이 맞다.

단지, Cloud Infra가 제공하는 K8S Node의 Security Rule에 의해서 UDP 트래픽이 Block되는 것이다.

따라서 Security Rule에 UDP 트래픽이 Pass 되도록 Rule을 추가하기만 하면 된다. (즉, Linux Firewall 설정 하듯이~)

 

AWS AKS, Azure AKS, Oracle OKE 모두 비슷하게 NLB가 UDP 트래픽을 처리하고 Security Rule도 비슷하기 때문에 Oracle의 OCI OKE만 이용해서 설명하면 아래와 같다.

 

아래의 순서로 메뉴/화면을 찾아서 들어간다.

[ Kubernetes Clusters (OKE) ]

-> Clusters 화면에서 특정 Cluster의 VCN을 선택/클릭한다.

-> VCN을 클릭하면, 여러개의 Subnets이 목록이 보여지는데 oke-svclbsubnet-xxxxoke-nodesubnet-yyyy을 선택하여 Security Lists를 확인한다.

-> [ Security Lists ] 화면에 있는 Rule 이름을 선택한다.

-> [ Ingress Rules ]와 [ Egress Rules ] 화면에서 UDP, TCP 트래픽을 모두 허용하도록 Rule을 추가한다.

     예를 들어, 115.33.55.0/24, 특정 UDP 포트(예: 9090), 특정 TCP 포트(예: 8080) 허용으로 설정하면 된다.

 

아래 화면을 참고~~~

 

 

 

이렇게 Security Rule을 추가하고, 다시 Public IP와 UDP 포트를 이용하여 트래픽을 보내보면, Pod 내부까지 UDP 트래픽이 잘 전달되는 것을 확인할 수 있다.

 

 


조심해야 할 사항:
  Security Rule 설정하고, 40초 후에 Traffic Test해야 한다.
  Node Security Rule이 적용되기 까지 40초가 걸리기 때문에 그 이후에 Traffic Test를 해야 제대로 Traffic이 Pod까지 전달된다.
  

 


생각해볼 내용:
  Node Security List에 TCP Rule을 추가할 때, 왜 Egress Rule도 추가해야 하는지 잘 이해가 안 된다.
  Cluster 외부에서 Ingress Rule에 따라 TCP Traffic을 허용해주면, ConnTrack DB에 Pin Hole 같은게 생기면서
  TCP의 응답 패킷도 알아서 Pass(Forward)시켜주는게 일반적인 Traffic 처리가 아닐까라고 생각했는데... 이게 아닌가 보다.
  아무튼 귀찮지만 Ingress에 추가한 Rule을 Egress에도 꼭 추가해야 한다. (잊지 말자 !!!)

 

 

 

 

참고하면 좋은 Web Docs

Oracle OCI Network Load Balancer 사용하기

https://thekoguryo.github.io/release-notes/20220315-support-for-oci-network-load-balancers/

 

Support for OCI Network Load Balancers

OKE에서 Service Type을 Load Balancer를 사용할때 이제는 OCI Network Load Balancer을 추가적으로 지원합니다.

thekoguryo.github.io

 

위 문서는 간단하게 사용법 위주로 설명되어 있고, 아래 문서는 내부 동작에 관해 자세하게 내용을 다루고 있다.

특히, Service Manifest의 externalTrafficPolicy: local 방식에 관해 궁금하다면 아래 문서를 보는 것이 좋다.

 

https://blogs.oracle.com/cloud-infrastructure/post/network-load-balancer-support-on-oracle-kubernetes-engine

 

Using a network load balancer for Kubernetes services

Announcing network load balancer support on Oracle Container Engine for Kubernetes.

orasites-prodapp.cec.ocp.oraclecloud.com

 

더 자세히 파고 들어가고 싶다면, Oracle 공식 Web Docs를 보길~~~

 

https://docs.oracle.com/en-us/iaas/Content/ContEng/Tasks/contengcreatingloadbalancer.htm

 

Defining Kubernetes Services of Type LoadBalancer

Include in the backend set:

docs.oracle.com

 

반응형

 

준비 작업: Oracle Cloud 사용을 위한 계정 생성

아래 Web Page에서 Oracle Cloud 사용을 위해서 Account를 생성한다.

https://cloud.oracle.com/

 

내 경우, 계정 생성하다가 마지막 "검증" 단계에서 실패했는데  Oracle에 전화해서 물어보니 

요즘 Block Chain Mining을 위해 Cloud Infra를 악용하는 사례가 있어서

계정 생성시 입력한 정보 중에서 블랙 해커로 의심되는 정보가 있으면, Oracle Machine Learning이 계정 생성을 Blocking 한다고 설명해줬다.

혹시 계정 생성하다 실패하면, 계정 정보를 다르게 해서 다시 생성하는 것이 정신 건강에 좋다.

 

 

OKE Cluster 생성하기

Oracle Cloud의 TOP 메뉴에서

[ Developer Services ] -> [ Kubernetes Cluters (OKE) ]

순서로 메뉴를 클릭하고, Quick Start 방식로 몇 가지 기본 설정 값만 정해주면 너무나 간단하게 Kubernetes Cluster가 생성된다.

 

주의: 
동일한 Spec의 Cluster 구축이라고 하더라도 Cluster Infra 상황에 따라 어떤 경우는 5분만에 Cluster가 생성되고,
어떤 경우는 15분이 넘도록 Cluster 생성이 완료되지 않는다.
그래서 마음편하게, Cluster 생성 버튼을 누르고 20분 정도 다른 업무를 하다가 오는 것이 좋다.

 

내 PC (Macbook)에서 OKE Cluster에 접근하기 (Bastion 구성)

Oracle이 너무 간단하게 만들어 놓아서 굳이 장황하게 설명할게 없다.

아래 Web Page에서 아래 빨간 번호 순서로 따라 하기만 하면 된다.

당연한 말이겠지만, 내 Macbook은 Public Network을 통해서 Oracle Cloud Infra에 접근해야 하니까, 아래 그림의 (6)번 절차에서 "VNC-Native public endpoint"와 관련된 명령을 복사해서 내 Macbook의 iTerm에 붙여 넣어야 한다.

 

 

위 절차를 끝낸 후, 내 Macbook의 iTerm 터미널에서 아래와 같이 명령을 수행하면 명령이 잘 수행되는 것을 확인할 수 있다.

 

$  kubectl  get node
NAME          STATUS   ROLES   AGE     VERSION
10.0.10.121   Ready    node    3m7s    v1.24.1
10.0.10.124   Ready    node    2m59s   v1.24.1
10.0.10.127   Ready    node    2m55s   v1.24.1
$

 

 

주의:
위 절차를 따라할 때, (5) ~ (6) 단계 사이에서 아래의 명령을 한번 수행해야 한다.
기존에 사용하던 KUBECONFIG 환경 변수가 설정된 경우라면, (6) 단계가 실패한다.
$  unset KUBECONFIG

 

 

 

Tip:
  [ Multi cluster를 운영하는 경우 ]
  예를 들어서 OKE kubernetes에서 cluster2, cluster3 등 2개의 cluster를 생성하여 운영하는 경우라면
  아래와 같이 .kube/config 파일 이름을 변경해서 사용하는 것을 추천.

 

$ mv $KUBECONFIG/config $KUBECONFIG/config.cluster2


$ cat .bashrc

... 중간 생략 ...

function use-oke-cluster2() {
  AA=$(printf "\033[")
  export KUBECONFIG=~/.kube/config.cluster2
  echo "${AA}32m"
  echo "Cluster Name      :" $(cat $KUBECONFIG | yq '.clusters[0].name')
  echo "Cluster API Server:" $(cat $KUBECONFIG | yq '.clusters[0].cluster.server')
  echo "${AA}0m"
}

... 중간 생략 ...

$ use-oke-cluster2

Cluster Name      : cluster-cja9kqodr9l
Cluster API Server: https://193.135.212.37:6443

$ kubectl get node
NAME          STATUS   ROLES   AGE    VERSION
10.0.10.115   Ready    node    11d    v1.25.4
10.0.10.117   Ready    node    11d    v1.25.4
$
반응형

2022년 11월 현재,  EFK(ElasticSearch, FluentBit, Kibana)를 설치해보려 한다.

공식 홈피에서 자료를 찾아서 읽고, 설치해야 하겠지만

오늘은 업무 때문에 해야 할 일이 많고, 여유 시간이 없어서 아래의 블로그를 읽고 따라해보려 한다.

만약 EFK 구축이 잘 되면, 추가로 글을 남겨보겠다 ^^

 

 

https://heartsavior.medium.com/kubernetes-%EC%97%90%EC%84%9C-efk-elasticsearch-fluentbit-kibana-stack-%EC%84%A4%EC%B9%98%ED%95%98%EA%B8%B0-17a4866a018

 

Kubernetes 에서 EFK (ElasticSearch/FluentBit/Kibana) stack 설치하기

역시 마찬가지로 디테일은 없다. 디테일은 레퍼런스 문서를 참고하자.

heartsavior.medium.com

 

반응형

 

Kubernetes Cluster를 설치한 날짜: 2022년 12월 21일

 


참고:
한땀 한땀 설치 과정을 이해하고 테스트하면서 kubernetes 내부 구성을 스터디하는 것이 목적이 아니라면,
아래 블로그를 읽고 kubespray로 설치하는 것을 추천한다.
  https://andrewpage.tistory.com/305

https://andrewpage.tistory.com/305

 

 

 

 

Kubernetes cluster(쿠버네티스 클러스터) 구축을 도와주는 여러 도구(kubeadm, kubespray, kops)가 있다.

이 문서에는 그런 kubernetes cluster 구축 도구 중에서 kubeadm을 이용하여 kubernetes cluster를 구축하는 방법을 설명한다.

 

참고로, kubeadm 도구가 가장 수작업이 많고 사람 손을 많이 탄다. 

그렇지만 Kubernetes 내부 구성을 이해하고 싶거나 작동 원리를 알고 싶다면 kubeadm 도구를 이용해서 설치하면 좋다.

즉, kubernetes를 공부하는 것이 목적이라면 kubeadm 관리 도구를 사용하는 것을 추천한다.

 

 

Kubernetes Cluster 구축을 위한 계획하기

Ubuntu 22.04 를 설치한 Master node와 Worker node를 준비한다.

  • Master Node: 1개 (master-0)
  • Worker Node: 2개 (worker-0, worker-1)

 

Master Node와 Worker Node 준비 작업

master node와 worker node 모두에서 아래의 작업을 수행한다.

kubernetes는 iptables를 이용하여 pod간 통신을 가능하게 한다. 따라서 iptables가 정상 동작하도록 하기 위해 아래와 같이 설정한다.

 

cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF

sudo modprobe overlay
sudo modprobe br_netfilter

# sysctl params required by setup, params persist across reboots
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1
EOF

# Apply sysctl params without reboot
sudo sysctl --system

 

모든 master node, worker node에서 swap 영역을 비활성화한다.

 

$  sudo sed -i '/swap/d' /etc/fstab

##
## 또는 위와 명령 대신, /etc/fstab 파일을 열어서 swap 과 관련있는 filesystem 항목을
## 주석으로 막아도 된다.
##

$  sudo swapoff -a

$  free -h
              total        used        free      shared  buff/cache   available
Mem:            15G        1.0G         13G         13M        925M         14G
Swap:            0B          0B          0B
$

 

방화벽(Firewalld)를 비활성화한다.

(원칙은 kubernetes가 사용하는 service port만 allow 설정해야 하지만, 여기서는 간단하게 firewalld를 종료하는 것으로 하겠다)

$  systemctl stop firewalld
$  systemctl disable firewalld

 

 

Container Runtime Interface(CRI) 설치하기 (여기서는 CRI-O를 설치!)

master node와 worker node 모두에서 아래의 작업을 수행한다.

$ sudo -s

$ apt update && sudo apt upgrade

$ OS=xUbuntu_22.04

##
## 주의: Kubernetes 1.25를 설치할 것이기 때문에
##      CRIO도 1.25를 설치하는 것이다. (즉, 2개의 버전이 일치해야 한다)
##

$ CRIO_VERSION=1.25

$ echo "deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/$OS/ /"|sudo tee /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list

$ echo "deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/$CRIO_VERSION/$OS/ /"|sudo tee /etc/apt/sources.list.d/devel:kubic:libcontainers:stable:cri-o:$CRIO_VERSION.list

$ curl -L https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable:cri-o:$CRIO_VERSION/$OS/Release.key | sudo apt-key add -

$ curl -L https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/$OS/Release.key | sudo apt-key add -

$ sudo apt update

$ sudo apt install cri-o cri-o-runc

$ apt show cri-o

$ systemctl enable --now crio.service

$ systemctl status crio

$ apt install cri-tools

$ crictl info

##
## cri-o가 잘 동작하는지 확인하기 위해 아래와 같이 container image를 pulling하는 테스트한다.
##

$ crictl pull busybox

$ crictl images

 

 

 

 

 

 

 


여기까지 설명이  master node, worker node에서 준비해야 할 작업이다.
이 다음 설명부터 실제 kubernetes cluster를 구축하기 위한 작업이다.

 

 


 

kubeadm, kubelet, kubectl 설치

kubeadm: kubernetes cluster를 구축하기 위한 명령 도구

kubelet: master node, worker node에서 데몬 프로세스로 기동되어 있으면서, container와 pod를 생성/삭제/상태를 감시한다.

kubectl: 사용자가 kubernetes cluster에게 작업 요청하기 위한 명령 도구 (예를 들어, 'pod를 생성해달라!'  'pod의 개수를 늘려달라!' 같은 사용자 명령을 kunernetes API server에게 전달)

 

아래의 명령을 따라 하여 kubeadm, kubelet, kubectl 명령 도구를 설치한다.

(모든 장비에서 수행해야 한다. 즉, Master Node와 Worker Node 모두에 해당하는 작업이다.)

 

$ sudo -s

##
## Update the apt package index and 
## install packages needed to use the Kubernetes apt repository:
## 

$ apt-get update

$ sudo apt-get install -y apt-transport-https ca-certificates curl


##
## Download the Google Cloud public signing key:
## 

$ curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg

##
## Add the Kubernetes apt repository:
##

$ echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list

##
## Update apt package index, install kubelet, kubeadm and kubectl, and pin their version:
##

$ apt-get update

$ apt-get install -y kubelet kubeadm kubectl

 

 

Kubernetes Cluster 생성하기

아래 명령을 master-0 node에서 수행한다.

 

##
## 주의: Master-0 노드에서만 수행해야 한다.
##

$ sudo -s

$  kubeadm init --apiserver-advertise-address 10.10.1.10
...
...


##
## Cluster 초기화는 2~3분 정도 걸린다.
## 초기화 작업이 끝나면 아래의 명령을 수행한다.
##

$ mkdir -p $HOME/.kube

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

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

 

위 명령을 수행하고 바로 Container Network Interface(CNI) 설치하는 작업을 수행해야 한다.

 

 

CNI 설치

CNI에는 많은 종류가 있지만, 사용하기 쉽고 대중적인 Calico 또는 Flannel CNI를 설치하겠다.

(Case A)  Calico를 설치하는 경우  <-- 추천

## 참고: 2023년 4월 23일 현재, v3.25.1을 설치하는 것을 권장.
$ kubectl apply  -f https://raw.githubusercontent.com/projectcalico/calico/v3.25.1/manifests/calico.yaml

##
## 주의: 위 명령을 수행하고 나서, `kubectl get pod -A` 명령으로 calico 관련 pod가 모두 기동했는지
##      확인한 후에 다음 절차를 수행해야 한다.
##

(Case B)  Flannel을 설치하는 경우 <-- 나는 개인적으로 별루~  (몇 달 운영하다가 Error  발생한 경험이 있어서)

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

 

 

※ 참고

위 명령 `kubectl apply -f .......calico.yaml` 을 수행 후 CNI 설치에 문제가 있었다면, Pod 'coredns-xxxxxx'  구동하지 못하고 'pending' 상태로 남게 된다.

그런 경우는 대부분 `kubeadm init --pod-network-cidr=10.244.0.0/16` 명령을 수행했을 때 사용했던 CIDR 값이 master node, worker node의 물리 주소와 겹치는 경우에 문제가 발생한다. 따라서 '10.244.0.0/16' 값이 아닌 다른 값으로 다시 변경해서 kubernetes cluster를 생성해보면 문제가 해결될 수 있다.

 

 

잠깐:
  위 명령을 수행하고 대략 3분 쯤 지난 후, 아래와 같이 Pod의 기동 상태를 확인하자!
  모든 Pod가 Running 상태로 변경된 이후에 나머지 작업을 진행한다.
root@master-a:~# kubectl get pod -A
NAMESPACE     NAME                                       READY   STATUS    RESTARTS   AGE
kube-system   calico-kube-controllers-74677b4c5f-88gzk   1/1     Running   0          55s
kube-system   calico-node-g2dcp                          1/1     Running   0          55s
kube-system   coredns-565d847f94-8mgrs                   1/1     Running   0          3m9s
kube-system   coredns-565d847f94-gsd5q                   1/1     Running   0          3m9s
kube-system   etcd-master-a                              1/1     Running   0          3m16s
kube-system   kube-apiserver-master-a                    1/1     Running   0          3m15s
kube-system   kube-controller-manager-master-a           1/1     Running   0          3m14s
kube-system   kube-proxy-vbg6h                           1/1     Running   0          3m10s
kube-system   kube-scheduler-master-a                    1/1     Running   0          3m15s
root@master-a:~#

 

 

Worker node joining

위에서 `kubeadm init` 명령을 수행했을 때, 출력되었던 메시지 중에 `kubeadm join ....` 과 같은 형태의 메시지가 있었을 것이다.

그 메시지를 복사해서  모든 worker node에서 수행한다.

# worker-0, worker-1에서 아래의 명령을 수행한다.
kubeadm join 10.1.3.170:6443 --token pdfjgjas.psdfjbh kajsdjhasdfv \
    --discovery-token-ca-cert-hash sha256:3nasklj46kj234k5lj12k3j4gkfdjjgdsfh51a3a686

위 명령이 수행된 이후에 master-0 node에서 아래의 명령으로 cluster 구축된 결과를 확인한다.

$  kubectl get node
NAME                         STATUS   ROLES                  AGE    VERSION
master-0.kube.sejong.space   Ready    control-plane,master   3m     v1.25.2
worker-0.kube.sejong.space   Ready    <none>                 1m     v1.25.2
worker-1.kube.sejong.space   Ready    <none>                 1m     v1.25.2

 

Kubernetes cluster 삭제 (Tear down)

만약 깔끔하게 kubernetes cluster를 지우고, 처음부터 다시 구축하고 싶다면 아래와 같이 cluster를 reset 한다.

$  apt install ipvsadm

$  kubeadm reset;   rm -rf  $HOME/.kube  /etc/kubernetes;   rm -rf /etc/cni;  ipvsadm --clear

 

 

Bastion Node 설정

위 설명에서는 kubectl 명령을 master-0 node에서 수행했다.

그러나 일반적으로 master-0에 직접 SSH 접속해서 kubectl 명령을 수행하는 것을 권장하지 않는다.

kubernetes cluster node는 운영 node이기 때문에 개발자가 접속하는 것이 바람직하지 않다.

(어쩌면, 보안 규정상 개발자가 master node에 SSH 접속하는 것 자체를 허용하지 않는 회사도 있을 것이다)

따라서 master-0 node가 아닌 본인의 PC(예를 들어 MacBook 같은 PC)에서 접속하는 방법을 사용하는 것을 권장한다.

방법은 간단하다.

master-0 node에 있는 /etc/kubernetes/admin.conf 파일을 내 PC(예를 들어 Macbook)에 복사하기만 하면 된다.

# MacOS를 사용한다고 가정하고 설명하겠다.
$  mkdir -p $HOME/.kube
$  cd $HOME/.kube
$  master-0 node의 '/etc/kubernetes/admin.conf' 파일을 내 PC로 내려받는다.
$  mv  admin.conf  config

# 내 PC에서 Kubernetes cluster의 API 서버로 잘 접속하는지 아래와 같이 명령을 수행해본다.
$  kubectl get node
NAME                         STATUS   ROLES                  AGE    VERSION
master-0.kube.sejong.space   Ready    control-plane,master   128m   v1.25.2
worker-0.kube.sejong.space   Ready    <none>                 126m   v1.25.2
worker-1.kube.sejong.space   Ready    <none>                 126m   v1.25.2
$

 


 

이 아래 부분에서 설명하는 작업 절차는 Kubernetes를 운영하는 데 있어서 꼭 필요한 것은 아니고, Web Dashboard로 좀 더 예쁘게 Kubernetes cluster를 모니터링하고 싶은 경우에 아래 Web Dashboard 설정 작업을 해주면 좋다.

 

Kubernetes Web Dashboard 설치 및 설정

내가 참고했던 Web docs(https://waspro.tistory.com/516) 가 있고, 이 문서에서 설명한 3가지 방식 중에서 3번째 방식(Kubernetes API Server 연동 방식)을 사용하는 것을 권장한다.

이 Web Docs에 설명이 잘 되어 있어서 내가 별도 설명할 필요 없을 것이고, 내가 수행했던 명령만 로그로 남겨보겠다.

 

$  kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-beta8/aio/deploy/recommended.yaml
$  kubectl proxy   &

# Service Account 생성

$  cat <<EOF | kubectl create -f -
 apiVersion: v1
 kind: ServiceAccount
 metadata:
   name: admin-user
   namespace: kube-system
EOF
$

# ClusterRoleBinding을 생성

$  cat <<EOF | kubectl create -f -
 apiVersion: rbac.authorization.k8s.io/v1
 kind: ClusterRoleBinding
 metadata:
   name: admin-user
 roleRef:
   apiGroup: rbac.authorization.k8s.io
   kind: ClusterRole
   name: cluster-admin
 subjects:
 - kind: ServiceAccount
   name: admin-user
   namespace: kube-system
EOF
$

# 사용자 계정의 Token 확인
$  kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep admin-user | awk '{print $1}') 
Name:         admin-user-token-p9ldd
Namespace:    kube-system
Labels:       <none>
Annotations:  kubernetes.io/service-account.name=admin-user
              kubernetes.io/service-account.uid=041cb7ec-946a-49b6-8900-6dc90fc08464

Type:  kubernetes.io/service-account-token

Data
====
ca.crt:     1025 bytes
namespace:  11 bytes
token:      eyJhbGciOiJSUzI1NiIsImtpZCI6InFmdGVUUnB6QmhoOHhlSDBJLUNLVHlEWWxpd2ZVaDhBVjZOQXE5TElhVWsifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhZG1pbi11c2VyLXRva2VuLWZ2dG5uIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImFkbWluLXVzZXIiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJjOGExZTY3MS00NmY1LTQwZjctODNkYy02YTE4N2NiYzkzYmYiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZS1zeXN0ZW06YWRtaW4tdXNlciJ9.lKKD4yEvlpFJ7-BNuPTyO3YRuFYYdQMgPX5azXwn4bZiki2Y886k1dnNM16L4YuA_SSahrPtitSzPfevlAoeC5msdDg1DKRdFuGuYkkI_u_KvOv7orMopDDgZs0zuXFrHIZa1-qiWbgvHfgokOMvndchCcMHyo8pKD3vdBAq_AxtGlCIPImkfALM_d41FrBKIXEjdoCcHkPu7Cz13UAxNRBRs-d274g2UNz-MUnNiomDhJlcYFXTXeooKjHhUiyoFLCgP-V6Wh_1QSCwdfYZGQ1bF0QcZINQZdwluyOtP43AjXHxdSBrAGIPfaY7qsBR_b2upuUDnQsA1w7qkaQB0g     <== 이 빨간색 token을 Web dashboard login 화면에 붙여 넣고, "Sign-in" 버튼을 누른다.
$

 

위와 같이 ServiceAccount와 ClusterRole을 설정하고, secret을 생성/등록한 후에 Web Browser에서 접속하면 된다.

 

접속 주소 예시:  http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/

 

 

 

 


 

Troubleshooting & How to clear the issue

kubeadm join  명령이 실패하는 경우.

대부분 master node에서 생성한지 1시간이 초과된 token 값을 이용해서 worker node에서 join하려고 하면 

'kubeadm join' 명령이 실패한다.

worker node 1, 2, ... 9 이런 식으로 순차적으로 작업하다가 보면, 거의 끝 부분에 있는 worker node 9는 이미 1 시간이 지난 뒤에

'kubeadm join'을 하게 되므로 종종 실패하게 된다.

그러나 심각한 문제는 아니고, master node에서 'kubeadm token create ...' 명령을 사용해서 다시 token 값을 생성해주기만 하면 된다.

아래와 같이 master node에서 token create하고, worker node에서 새로 만들어진 token 값으로 `kubeadm join'하면 된다.

##
## On master node.
##
$ kubeadm token create --print-join-command

kubeadm join 10.10.3.33:6443 --token z53s7g.aa...zc --discovery-token-ca-cert-hash sha256:372...3a686


##
## On worker node.
##
$ kubeadm join 10.10.3.33:6443 --token z53s7g.aa...zc --discovery-token-ca-cert-hash sha256:372...3a686

[preflight] Running pre-flight checks
[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Starting the kubelet
[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...

This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.

Run 'kubectl get nodes' on the control-plane to see this node join the cluster.

$


##
## 위와 같이 worker node의 joining이 성공하면, 
## 그 동안 activating (auto-restart) 상태였던 kubelet에 아래와 같이 active(running) 상태로 바뀐다.
## On worker node.
##

$ systemctl status kubelet

● kubelet.service - kubelet: The Kubernetes Node Agent
   Loaded: loaded (/usr/lib/systemd/system/kubelet.service; enabled; vendor preset: disabled)
  Drop-In: /usr/lib/systemd/system/kubelet.service.d
           └─10-kubeadm.conf
   Active: active (running) since Thu 2021-11-11 15:38:54 KST; 17s ago
   ...
   ...
   
 $

위와 같이 Active: active (running) 상태로 출력되면, 정상적으로 kubelet이 기동되고 Master node와 연동된 것이다.

 

 


 

 

 

 

##
## 채용 관련 글
##
제가 일하고 있는 기업 부설연구소에서 저와 같이 연구/개발할 동료를 찾고 있습니다.
(이곳은 개인 블로그라서 기업 이름은 기재하지 않겠습니다. E-mail로 문의주시면 자세한 정보를 공유하겠습니다.)

근무지 위치:
  서울시 서초구 서초동, 3호선 남부터미널역 근처 (전철역 출구에서 회사 입구까지 도보로 328m)
필요한 지식 (아래 내용 중에서 70% 정도를 미리 알고 있다면 빠르게 협업할 수 있음):
  - 운영체제 (학부 3~4학년 때, 컴퓨터공학 운영체제 과목에서 배운 지식 수준):
    예를 들어, Processor, Process 생성(Fork)/종료, Memory, 동시성, 병렬처리, OS kernel driver  
  - Linux OS에서 IPC 구현이 가능
    예를 들어, MSGQ, SHM, Named PIPE 등 활용하여 Process간 Comm.하는 기능 구현이 가능하면 됨. 
  - Algorithm(C언어, C++ 언어로 구현 가능해야 함)
    예를 들어, Hashtable, B-Tree, Qsort 정도를 C 또는 C++로 구현할 수 있을 정도 
  - Network 패킷 처리 지식(Layer 2 ~ 4, Layer 7)
    예를 들어, DHCP Server/Client의 주요 Feature를 구현할 정도의 능력이 있으면 됨.
  - Netfilter, eBPF 등 (IP packet hooking, ethernet packet 처리, UDP/TCP packet 처리)
  - IETF RFC 문서를 잘 읽고 이해하는 능력 ^^
  # 위에 열거한 내용 외에도 제가 여기 블로그에 적은 내용들이 대부분 업무하면서 관련이 있는 주제를 기록한 것이라서
  # 이 블로그에 있는 내용들을 잘 알고 있다면, 저희 연구소에 와서 연구/개발 업무를 수행함에 있어서 어려움이 없을 겁니다.
회사에서 사용하는 프로그래밍 언어:
  - 프로그래밍 언어: C, C++, Go
    (참고: 아직 연구소 동료들이 Rust를 사용하진 않습니다만, 새 언어로써 Rust를 사용하는 것을 고려하는 중)
근무 시간:
  - 출근: 8~10시 사이에서 자유롭게 선택
  - 퇴근: 8시간 근무 후 퇴근 (오후 5시 ~ 7시 사이)
  - 야근 여부: 거의 없음 (내 경우, 올해 상반기 6개월간 7시 이후에 퇴근한 경우가 2회 있었음)
  - 회식 여부: 자유 (1년에 2회 정도 회식하는데, 본인이 집에 가고 싶으면 회식에 안 감. 왜 참석 안 하는지 묻지도 않음)
외근 여부:
  - 신규 프로젝트 멤버 -> 외근 전혀 하지 않음 (나는 신규 프로젝트만 참여해서 지난 1년 동안 한번도 외근 없었음)
  - 상용 프로젝트 멤버 -> 1년에 5회 미만 정도로 외근
팀 워크샵 여부:
  - 팀 워크샵 자체를 진행하지 않음. (워크샵 참석하는 거 싫어하는 개발자 환영 ^^)
연락처:
  - "sejong.jeonjo@gmail.com"  # 궁금한 점은 이 연락처로 문의주세요.
  - 블로그 비밀 댓글 (제가 하루에 한번씩 댓글 확인하고 있음)
원하는 인재상:
  - 우리 부설연구소는 "긴 호흡으로 프로젝트를 진행"하기 때문에 최소 2년간 한 가지 주제를 꾸준하게 연구/개발할 수 있는 개발자를 원함.
  - 우리 부설연구소는 자주적으로 연구 주제를 찾아서 업무를 하기 때문에 능동적으로 생각하고 행동하는 동료를 원함.
  - 차분하게 연구 주제에 몰입하고, 해법을 찾는 것을 즐기는 사람.
내가 느끼는 우리 연구소의 장점:
  - 갑/을 관계가 없음. (제가 근무하고 있는 연구소는 SI업종이 아니라서 갑/을 회사 개념이 없음)
  - 연구소 자체적으로 연구 주제를 발굴하고 시스템을 개발하기 때문에 개발 일정에 대한 스트레스가 적음
  - 빌딩 전체를 우리 회사가 사용하므로 분위기가 산만하지 않음.
  - 근처에 예술의전당, 우면산 둘레길이 있어서 점심 시간에 산책하기 좋음 ^^
  - 연구소 동료들 매너가 Good (2년간 일하면서 한번도 감정에 스크레치 생기거나 얼굴 붉히며 싸운 적 없음 ^^)

 

+ Recent posts