0부터 시작하는 Kubernetes 공부 - Kubernetes 환경 구성 & MetalLb

Jaehong Lee·2022년 9월 5일
3
post-thumbnail

1. Kubernetes 환경 구성

swapoff -a

  • swapoff -a 는 각 노드에서 가상 메모리를 사용하는 옵션이다
    • 허나 k8s 환경에서는 모든 노드의 일관성을 유지하기 위해 메모리도 같아야한다. 따라서 가상 메모리를 사용하는 옵션을 사용해서는 안된다. 이를 주석 처리 해야 한다
root@manager:/home/user1# cat /etc/fstab 
UUID=5535a33d-56e1-4b72-a7d6-dcb513bd1a4b /               ext4    errors=remount-ro 0       1
# /boot/efi was on /dev/sda1 during installation
UUID=0889-C55E  /boot/efi       vfat    umask=0077      0       1
#/swapfile                                 none            swap    sw              0       0 #이 부분을 주석처리
  • 해당 부분을 주석처리해주자. 만약, swap 메모리를 사용하는 상태에서 클러스터를 구성할 시 오류가 발생할 수 있다

Cluster 구성 - Token 발행

kubeadm init --apiserver-advertise-address 211.183.3.100
  • master node 에서 Kubernetes 클러스터 초기화 및 Token 을 발행하자
kubeadm join 211.183.3.100:6443 --token txl691.qficfxf8ramv1wd2 \
        --discovery-token-ca-cert-hash sha256:55985f2922219aa58dcc448638c2bf33231eead697c49faaf12951b8a741817e 
  • 명령 실행시 나온 결과 명령어를 worker node 에 입력하면 Cluster 에 Join 된다
    • 클러스터 초기화 : kubeadm reset
    • 클러스터 시작 : kubeadm init

사용자 권한

  • Token 을 발행하면 해당 사용자 계정은 admin 계정의 권한을 가지게 되고, Node 는 master Node 가 된다. 만약, admin 계정 권한이 풀린다면 아래 명령을 실행하자
# 일반 사용자가 kubectl 을 사용하기 위해서
mkdir -p $HOME/.kube # 디렉토리 생성
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config # k8s admin 계정 설정 파일 복사
sudo chown $(id -u):$(id -g) $HOME/.kube/config # 복사한 파일의 소유주를 현재 사용자, 그룹으로 변경

# root 사용자가 kubectl 을 사용하기 위해서
export KUBECONFIG=/etc/kubernetes/admin.conf # 환경 변수에 추가, export 는 전역 변수를 의미한다
  • 현재 사용자가 쿠버네티스의 admin 계정에 대한 설정 내용이 포함된 파일을 관리할 수 있다 -> 현재 사용자가 쿠버네티스 관리자로 등록된다
    • 일반 사용자 권한 같은 경우 터미널 종료 후에도 유지되지만, 루트 사용자 권한은 터미널 종료 후 유지가 안될 수 있으므로 해당 명령어를 .bashrc 에 입력해주자

  • KUBECONFIG 는 Service Account 의 정보를 누구로 할 것인지 파일을 지정하는 변수이다
    • /etc/kubernetes/admin.conf 는 쿠버네티스 전체 관리자 admin 계정 정보를 가지고 있다
    • 즉, KUBECONFIG 는 admin 을 지정하는 변수이다. 해당 변수에 인증서, key 가 들어간 사용자의 admin.conf 를 지정하여 현재 사용자를 admin 으로 지정한다

user 가 Kubernetes 에 admin 계정으로 사용하기 위해서는 admin.conf 가 필요하다

  • 일반 사용자의 경우, 해당 /etc/kubernetes/admin.conf 를 자신의 디렉토리로 가져와서 KUBECONFIG 에 일반 사용자의 admin.conf 를 지정하여, 일반 사용자를 admin 으로 지정해야 한다

만약 재부팅시 오류가 난다면

export KUBECONFIG=/etc/kubernetes/admin.conf 
  • 위 명령어를 다시 입력하거나
KUBECONFIG=/etc/kubernetes/admin.conf
  • 처음 실행시 위 명령어를 자동 실행하게 .bashrc 에 등록하자

worker Node Join

root@worker1:/home/user1# kubeadm join 211.183.3.100:6443 --token txl691.qficfxf8ramv1wd2 \
>         --discovery-token-ca-cert-hash sha256:55985f2922219aa58dcc448638c2bf33231eead697c49faaf12951b8a741817e
[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.
  • master 에서 클러스터 초기화시 생성된 Token Join 명령어를 통해 클러스터에 Join 시키자

Calico 애드온 추가 및 확인

Pod 간 통신을 위한 Overlay Network 를 구성하자

docker login # 도커 로그인
kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml # yaml 파일로 calico 배포
  • Docker login 후 Calico 를 배포하자
kubectl get pod -n kube-system # kube-system 에 속한 Pod 확인
  • Calico Pod 확인

Calico 설치를 위한 yaml 파일을 살펴보자

root@manager:/home/user1# wget https://docs.projectcalico.org/manifests/calico.yaml
--2022-09-05 10:36:42--  https://docs.projectcalico.org/manifests/calico.yaml
Resolving docs.projectcalico.org (docs.projectcalico.org)... 34.143.223.220, 52.220.193.16, 2406:da18:880:3802:371c:4bf1:923b:fc30, ...
Connecting to docs.projectcalico.org (docs.projectcalico.org)|34.143.223.220|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 234906 (229K) [text/yaml]
Saving to: ‘calico.yaml’

calico.yaml               100%[=====================================>] 229.40K   614KB/s    in 0.4s    

2022-09-05 10:36:43 (614 KB/s) - ‘calico.yaml’ saved [234906/234906]

root@manager:/home/user1# cat calico.yaml | grep image:
          image: docker.io/calico/cni:v3.24.1
          image: docker.io/calico/cni:v3.24.1
          image: docker.io/calico/node:v3.24.1
          image: docker.io/calico/node:v3.24.1
          image: docker.io/calico/kube-controllers:v3.24.1
  • 3 개의 이미지를 사용한다

K8S 동작을 위한 Pod 확인

manager에 있는 api, 스케줄러, 컨트롤러 등은 모두 pod 형태로 생성되어 서비스를 제공한다. 또한 CoreDNS, calico도 pod 형태로 서비스가 제공된다. 따라서 이미지 다운로드 후 pod 생성의 단계를 거쳐야 한다

kubectl get pod -n kube-system | grep proxy # proxy 확인
  • Proxy 가 있는지 확인하자
root@manager:/home/user1# kubectl get pod -n kube-system | grep scheduler
kube-scheduler-manager                     1/1     Running   0          32m
  • 스캐줄러를 확인하자. manager 의 것 하나가 있다
root@manager:/home/user1# kubectl get pod -n kube-system | grep coredns
coredns-558bd4d5db-jqbrm                   1/1     Running   0          48m
coredns-558bd4d5db-v55cn                   1/1     Running   0          48m
  • CoreDns 확인

    노드에 생성된 각각의 포드는 별도의 독립적인 주소와 이에 해당하는 도메인이름이 할당된다. 우리는 이 정보가 저장된 coreDNS 를 통해 통신시킬 수 있다

CNI 란?

p. 99

CNI(Container Network Interface)는 컨테이너들과의 통신을 위해 개발된 인터페이스이며 표준화를 통해 어떠한 컨테이너든 상관 없이 연결이 가능하도록 해준다. 크게 L2와 L3로 구분한다. 즉, 쿠버네티스 네트워크에 오버레이 네트워크를 구성해주고 파드와 호스트 인터페이스를 연결해주는 부분을 별도의 모듈로 분리한 플러그인을 만들기 위한 표준이다

CNI는 호스트 네트워크 인터페이스의 각종 네트워크 기능들(iptables, 커널 라우팅, 터널링, 브릿지)을 사용하게 해준다

  • L2 : 각각의 노드에 나뉘어 배포된 모든 pod를 하나의 '가상 스위치'에 연결하여 통신시킬 수 있다

  • L3 : 각 네트워크 간 통신을 가상의 라우터를 사용하여 라우팅한다. 또한 BGP를 제공하여 회사 내에서 보유하고 있는 독립된 공인 주소 대역을 ISP와의 통신에 활용할 수 있다

L2와 L3 중 어느 것을 사용하더라도 pod 간 통신에는 문제 없다

master Node Pod 확인

root@manager:/home/user1# kubectl get pod -n kube-system 
NAME                                       READY   STATUS    RESTARTS   AGE
calico-kube-controllers-867d8d6bd8-zjtvl   1/1     Running   0          38m
calico-node-px2vp                          1/1     Running   0          38m
calico-node-qmb6g                          1/1     Running   0          38m
calico-node-r9p9m                          1/1     Running   0          38m
calico-node-vd987                          1/1     Running   0          38m
coredns-558bd4d5db-jqbrm                   1/1     Running   0          50m
coredns-558bd4d5db-v55cn                   1/1     Running   0          50m
etcd-manager                               1/1     Running   0          50m
kube-apiserver-manager                     1/1     Running   0          50m
kube-controller-manager-manager            1/1     Running   0          50m
kube-proxy-2ttkz                           1/1     Running   0          41m
kube-proxy-f25xm                           1/1     Running   0          41m
kube-proxy-t47dm                           1/1     Running   0          50m
kube-proxy-x2z4k                           1/1     Running   0          41m
kube-scheduler-manager                     1/1     Running   0          50m
  • kube system namespace 에 속한 Pod 리스트와 동작 여부를 확인하자

2. MetalLB 구성하기

참조 ) https://metallb.universe.tf/usage/

퍼블릭 환경의 경우에는 pod와 외부 사용자간 연결을 위해 손쉽게 LB를 이용할 수 있다. 하지만 on-premise에서는 LB 서비스를 이용할 수 없다. 이를 해결하기 위해 metallb를 사용하면 LB 이용이 가능하다

생성된 metallb 에 어떠한 공인주소를 LB Pod 를 통해 전달할 것인지를 결정할 ConfigMap 을 작성하고 이를 배포한다

MetalLB 의 구조

MetalLB Controller & Speacker 는 Cluster 시스템 상에 하나만 배포되야한다. 허나, 여러 ns 에서는 각기 다른 주소를 관리하길 원한다. ConfigMap 을 사용하여 LB 서비스 를 배포할 때, Controller 는 ConfigMap 을 참조하여 해당 Namespace 의 서비스에게 할당해준다. 이때 LB 서비스 배포시 사용할 address pool 의 name 을 지정하여, Controller 는 ConfigMap 에서 해당 name 의 address pool 에 지정된 네트워크 대역과 Protocol 을 확인하고, 이를 각 Node 의 speaker 에게 전달한다. speaker 는 Ip 주소와 Protocol 을 해당 Node 의 LB 서비스에 할당한다

  • 해당 Namespace 에 속한 LB 서비스 들은 배포시 address pool 의 name 을 지정하면, 자동으로 Controller 가 ConfigMap 을 참조하여, name 에 맞는 address pool 에 정의된 네트워크 대역과 Protocol 을 speaker 로부터 할당 받는다

  • 약간 위와 같은 대략적인 느낌으로 보면 된다

Namespace 생성

root@manager:/home/user1# kubectl create ns metallb-system
namespace/metallb-system created
  • namespace 를 생성하자. 이름은 지정된 것이다

    다른 ns 에서 metallb 를 사용하기 위해 접근해야 하므로 metallb-system 이라는 고정된 이름의 ns 필요하다. 이 이름은 사용자 임의로 바꿀 수 있는 것이 아니다

root@manager:/home/user1# kubectl get ns
NAME              STATUS   AGE
default           Active   61m
kube-node-lease   Active   61m
kube-public       Active   61m
kube-system       Active   61m
metallb-system    Active   37s
  • 생성됬는지 확인하자

controller, speaker 구성을 위한 manifest 파일 배포

root@manager:/home/user1# kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.12.1/manifests/metallb.yaml
  • metalLB controller와 metalLB speaker 를 배포하자
    • MetalLB 컨트롤러 : 작동 방식(Protocol, 프로토콜)을 정의하고 EXTERNAL-IP를 부여해 관리
    • MetalLB 스피커 : 정해진 작동 방식(L2/ARP, L3/BGP)에 따라 경로를 만들 수 있도록 네트워크 정보를 광고하고 수집해 각 파드의 경로를 제공한다. 이는 데몬셋으로 Node 당 반드시 하나씩 존재한다

ConfigMap 배포

apiVersion: v1
kind: ConfigMap
metadata:
  namespace: metallb-system
  name: config
data:
  config: |
    address-pools:
    - name: default
      protocol: layer2
      addresses:
      - 211.183.3.201-211.183.3.211 # 해당 네트워크 대역으로 LB 생성 
      - 211.183.3.231-211.183.3.239 # 해당 네트워크 대역으로 LB 생성 
  • protocol 과 할당해줄 네트워크 대역과 Protocol 을 설정하여 ConfigMap 을 배포하자. 이는 LB 서비스 배포에 참조되어진다
    • configmap 은 metallb 의 config 부분에 data 를 하나로 보내준다. 이를 위해 | 사용
    • address-pools name 은 LB 서비스에 Ip 및 Protocol 을 할당해줄 때, 사용하고자 하는 것을 구분하기 위해 사용한다. 즉, 원하는 네트워크 대역 및 Protocol 을 할당해주고 싶으면, LB 서비스 배포시 해당 address-pools name 을 metallb.universe.tf/address-pool 에 지정해줘야 한다. 만약, LB 배포시 해당 address-pools name 을 따로 명시하지 않으면, 첫번째 pool 부터 내려가며 사용한다. 이는, 만약 첫번째 pool 의 Ip 를 다 사용하고 있다면, 그 다음인 두번째 pool 을 사용한다는 것이다. default 는 단순히 이름이다
      • 즉, name 은 임의로 사용할 수 있다. 이는 metallb.universe.tf/address-pool 에서 사용하고자 하는 pool 을 지정할 때 사용한다. 이왕이면 ns 랑 같은 이름으로 하는게 구분하기 좋다
    • metadata 의 namespace 는 Data 를 MetalLB 에 전달해야 하므로, MetalLB 의 ns 인 metallb-system 을 지정해야 한다
root@manager:/home/user1/k8slab# kubectl apply -f metallb.yaml 
configmap/config created
  • 배포해주자

Deployment & LB 배포 및 확인

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec: # 아래는 ReplicaSet 설정 
  replicas: 3
  selector: # 아래의 label 개수를 확인하여 pod 관리 
    matchLabels:
      app: webserver 
  template: # 아래는 pod 구성 
      metadata: 
        name: my-webserver # Pod의 이름 
        labels:
          app: webserver 
      spec: # 아래 부분은 컨테이너 구성 내용 
        containers: 
        - name: my-webserver # 컨테이너의 이름 
          image: nginx 
          ports:
          - containerPort: 80 

---

apiVersion: v1 
kind: Service
metadata:
  name: nginx-lb 
spec:
  ports:
  - name: web-port
    port: 80
  selector:
    app: webserver
  type: LoadBalancer 
  • nginx 를 이용한 Deployment 와 LB 서비스를 배포하자
root@manager:/home/user1/k8slab# kubectl get pod,svc
NAME                                    READY   STATUS              RESTARTS   AGE
pod/nginx-deployment-5fdcfffc56-5szpw   1/1     Running             0          67s
pod/nginx-deployment-5fdcfffc56-ctbhm   1/1     Running             0          67s
pod/nginx-deployment-5fdcfffc56-gqk7l   0/1     ContainerCreating   0          67s

NAME                 TYPE           CLUSTER-IP       EXTERNAL-IP     PORT(S)        AGE
service/kubernetes   ClusterIP      10.96.0.1        <none>          443/TCP        119m
service/nginx-lb     LoadBalancer   10.110.108.162   211.183.3.201   80:30105/TCP   67s
  • LB 의 EXTERNAL-IP 로 접속해보자
  • 잘 접속된다

한 번에 삭제하기

  • 해당 디렉토리의 yaml 파일로 배포한 모든 것을 삭제해준다

3. yaml 작성하기

  1. 확장자는 yaml, yml 로 작성한다
  2. tab 은 기본적으로 인식하지 않으므로, space bar 사용
  3. 주석은 json 에서는 기본적으로 허용하지 않지만, yaml 에서는 # 을 쓰면 된다
  4. 두 가지 이상의 작업을 하나의 파일에 작성시 --- 로 구분
  5. 리스트 사용 가능
     5.1 [  ,  ,  ]  -> ["gildong", "chulsoo", "minsoo"]
      5.2 
          - 
          - 
  6. 기본적으로 yaml 은 string 이다
    '
    abc
    cdf
    '   #abccdf 로 출력된다
  7. 러줄로 작성된 내용을 사진찍듯이 그대로 옮기고 싶다면 | 를 이용할 수 있다. 기본적으로 한 줄 뒤에는 \n 이 생략되어 있다. 만약 | 아래에 한줄을 비웠다면 이 역시 그대로 한줄 비우기가 전달된다. 추가적으로 | 뒤에 - 를 붙이면 마지막 라인이 비워져 있어도 이를 지워준다

alias 를 설정해서 k8s 를 간편하게 사용하자

alias k='kubectl'
  • 이제 명령 입력시 k 만 입력하면 된다
profile
멋진 엔지니어가 될 때까지

0개의 댓글