Kubernetes 1.28 에서 MetalLB 설치하기

반응형

MetalLB 를 설치하면 LoadBalancer 를 사용할 수 있는데, 이는 외부에서 접근하는 공인 IP 를 Pod 에 부여함으로써 온전히 애플리케이션의 포트를 NodePort (30000~32767) 와 같이 임의 포트가 아닌 공식 표준 포트를 사용할 수 있게 됩니다.

아래 예제의 Kubernetes 환경은 1.28 버전이며, 모든 명령은 master (control-plane) 서버에서 진행하였습니다.

 

공식 홈페이지 Documents : https://metallb.universe.tf/installation/

 

 

1. kube-proxy 구성 편집

 

kube-proxy 를 사용하는 경우 ARP 모드를 사용해야 합니다.

아래 명령을 이용해 kube-proxy 구성을 편집합니다.

# kubectl edit configmap -n kube-system kube-proxy
configmap/kube-proxy edited

...
ipvs:
  strictARP: true
...

 

위 내용으로 저장합니다.

 

 

2. MetalLB 설치

 

MetalLB 컴포넌트 등을 하나의 파일로 설치합니다. 작성일 기준 최신 버전은 0.13.10 입니다.

# kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.10/config/manifests/metallb-native.yaml

 

MetalLB 관련 Pod 가 잘 생성되었는지 확인합니다.

Running 상태까지 되는데 시간이 소요될 수 있습니다. (모든 Pod 1/1)

# kubectl get pod -n metallb-system
NAME                          READY   STATUS    RESTARTS   AGE
controller-5c6b6c8447-4kzpl   1/1     Running   0          15m
speaker-6fxtx                 1/1     Running   0          15m
speaker-7gg7s                 1/1     Running   0          15m
speaker-z284z                 1/1     Running   0          15m

 

 

3. IP Pool 생성

 

라우팅 처리를 하기위해 보유하고 있는 IP 리스트를 등록합니다.

Pod 에서 IP 를 사용할 수 있도록 상단 스위치단에서 IP 설정이 이루어져 있어야 합니다.

아래는 28비트 대역 2개를 추가해 보았습니다.

실제로 Pod 에 할당하려는 IP 범위를 적어줍니다.

# vi ippool.yaml

apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: first-pool
  namespace: metallb-system
spec:
  addresses:
  - 115.68.142.130-115.68.142.140
  - 115.68.142.146-115.68.142.156

 

IP 를 추가할때는 서브넷 마스크를 별도로 지정하지 않아도 주소 범위 내의 모든 IP 주소를 사용할 수 있도록 인식합니다. MetalLB 는 주소 범위를 기반으로 자동으로 서브넷 마스크를 계산하기 때문입니다.

작성한 yaml 파일을 적용합니다.

# kubectl apply -f ippool.yaml

ipaddresspool.metallb.io/first-pool created

 

* 에러 발생시 ----------

여기에서 다음과 같은 에러가 발생했을때 조치방법 입니다.

Error from server (InternalError): error when creating "ippool.yaml": Internal error occurred: failed calling webhook "ipaddresspoolvalidationwebhook.metallb.io": failed to call webhook: Post "https://webhook-service.metallb-system.svc:443/validate-metallb-io-v1beta1-ipaddresspool?timeout=10s": dial tcp 10.102.110.54:443: connect: connection refused

 

이때는 아래와 같이 metallb-webhook-configuration 설정을 삭제하고 다시 실행해 보세요.

# kubectl delete validatingwebhookconfigurations metallb-webhook-configuration
validatingwebhookconfiguration.admissionregistration.k8s.io "metallb-webhook-configuration" deleted

----------------------------

 

L2 네트워크를 생성하고 적용합니다.

# vi l2.yaml

apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: my-l2
  namespace: metallb-system
spec:
  ipAddressPools:
  - first-pool

 

# kubectl apply -f l2.yaml

l2advertisement.metallb.io/my-l2 created

 

 

4. 테스트 (Pod 생성 및 IP 연결)

 

테스트를 위해 Nginx Pod 를 생성하고 공인 IP 를 할당하여 외부 통신이 되는지 확인합니다.

# kubectl create deploy nginx --image=nginx

deployment.apps/nginx created

 

# kubectl expose deploy nginx --port 80 --type LoadBalancer

service/nginx exposed

 

# kubectl get services
NAME         TYPE           CLUSTER-IP      EXTERNAL-IP      PORT(S)        AGE
kubernetes   ClusterIP      10.96.0.1       <none>           443/TCP        3d
nginx        LoadBalancer   10.111.72.120   115.68.142.130   80:32088/TCP   20m

 

Kubernetes Cluster 외부의 네트워크에서 출력된 IP 로 접근하여 Nginx 가 열리는지 확인합니다.

# curl http://115.68.142.130

 

반응형

댓글()

Kubernetes 1.28 에서 worker 노드 제거 및 추가하기

반응형

1. 노드 제거하기

 

시스템 장애 또는 OS 재설치 등의 이유로 worker 노드 하나를 제거해야 할 수 있습니다.

제거하기 전의 Cluster 상태는 아래와 같습니다.

 

# kubectl get nodes
NAME      STATUS                     ROLES           AGE     VERSION
master    Ready                      control-plane   2d22h   v1.28.1
worker1   Ready                      <none>          2d22h   v1.28.1
worker2   Ready                      <none>          2d22h   v1.28.1

 

worker2 노드를 Kubernetes 클러스터에서 제거하고 다시 연결하는 프로세스는 다음과 같이 진행할 수 있습니다.
주의할 점이 하나 있는데, 노드를 클러스터에서 제거하면 해당 노드에서 실행 중인 모든 컨테이너와 Pod가 중지됩니다.

먼저 worker2 노드에서 실행 중인 Pod 를 다른 노드로 옮기거나 제거해야 합니다.

이 명령어는 worker2 노드에서 실행 중인 Pod 를 다른 노드로 옮기고, DaemonSet Pod 는 무시합니다.

# kubectl drain worker2 --ignore-daemonsets

node/worker2 cordoned
Warning: ignoring DaemonSet-managed Pods: kube-system/kube-proxy-8tqss
node/worker2 drained

 

이 상태로 node 리스트를 확인해보면, 해당 노드에 스케쥴링이 비활성화 된 것이 보입니다.

# kubectl get nodes
NAME      STATUS                     ROLES           AGE     VERSION
master    Ready                      control-plane   2d22h   v1.28.1
worker1   Ready                      <none>          2d22h   v1.28.1
worker2   Ready,SchedulingDisabled   <none>          2d22h   v1.28.1

 

worker2 노드를 클러스터 목록에서 제거합니다.
# kubectl delete node worker2

# kubectl get nodes
NAME      STATUS   ROLES           AGE     VERSION
master    Ready    control-plane   2d22h   v1.28.1
worker1   Ready    <none>          2d22h   v1.28.1

 

 

2. 노드 추가하기

 

worker2 노드를 다시 클러스터에 추가하려면 해당 노드를 다시 등록해야 합니다.

OS 를 재설치 한 경우 worker 노드의 환경 구성은 아래 URL 을 참고합니다.

https://sysdocu.tistory.com/1851

 

worker 노드 준비가 되었으면 master 서버에서 토큰 생성과 함께 join 명령을 출력합니다.

생성된 토큰의 유효 시간은 1일 (24시간) 이며, --ttl 1h 이런 옵션을 줄 경우 토큰 유효 시간을 지정할 수 있습니다.

(master 노드에서)

# kubeadm token create --print-join-command
kubeadm join 115.68.142.104:6443 --token pa3e56.88nw5c48vmbyr522 --discovery-token-ca-cert-hash sha256:82020f205bd07cd7b964a40227f33db5109adc523f042e742d7c6ec8443efbdc

 

(worker2 노드에서)

master 노드에서 출력된 명령줄을 실행합니다.

# kubeadm join 115.68.142.104:6443 --token pa3e56.88nw5c48vmbyr522 --discovery-token-ca-cert-hash sha256:82020f205bd07cd7b964a40227f33db5109adc523f042e742d7c6ec8443efbdc

 

추가된 worker2 노드를 확인합니다.

(master 노드에서)

# kubectl get nodes
NAME      STATUS   ROLES           AGE     VERSION
master    Ready    control-plane   2d23h   v1.28.1
worker1   Ready    <none>          2d23h   v1.28.1
worker2   Ready    <none>          3m44s   v1.28.1

 

* 에러 조치

master 서버에서 Pod 생성시 에러가 발생한다면 추가한 worker 노드에서 다음과 같이 조치 가능합니다.

 

[ 에러 ]

Events:
  Type     Reason                  Age                   From               Message
  ----     ------                  ----                  ----               -------
  Normal   Scheduled               37m                   default-scheduler  Successfully assigned ceph-csi-rbd/ceph-csi-rbd-nodeplugin-n9b2v to worker3
  Warning  FailedCreatePodSandBox  31m (x26 over 37m)    kubelet            Failed to create pod sandbox: rpc error: code = Unknown desc = cri-o configured with cgroupfs cgroup manager, but received systemd slice as parent: /kubepods.slice/kubepods-besteffort.slice/kubepods-besteffort-podd3fc3e78_f49c_4239_b271_55e406fd0b76.slice

 

[ 해결 ]

아래 kubelet 설정 파일에서 cgroup driver 를 바꿔줍니다.

(추가된 worker 노드에서)

# vi /usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf

...

Environment="KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml --cgroup-driver=cgroupfs"
...

 

# systemctl daemon-reload
# systemctl restart kubelet

 

반응형

댓글()

Ubuntu 22.04 에서 CRI-O, Kubernetes 1.28 Cluster, Calico 설치 및 애플리케이션 배포

반응형

Kubernetes 는 컨테이너의 생성, 배포, 실행을 하는 등 컨테이너를 관리하는 오픈소스 플랫폼 입니다.

여기에서는 Ubuntu 22.04 버전의 서버 3대로 (master 노드 1대 / worker 노드 2대) Kubernetes 1.28 을 구성하는 방법에 대해 설명합니다.

- 공식 Documents : https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/

 

 

1. CRI-O 설치

 

CRI-O 공식 홈페이지 : https://cri-o.io

 

Pod 를 실행하고 관리할 수 있도록 Containerd 나 CRI-O 와 같은 컨테이너 런타임을 설치해야 합니다.

여기에서는 CRI-O 를 설치하도록 하겠습니다.

 

(모든 노드에서)

서버별로 호스트네임을 설정하고 각 노드에 호스트명으로 통신 가능하도록 hosts 파일에 추가합니다.

# hostnamectl set-hostname master      // master 노드에서

# hostnamectl set-hostname worker1    // worker1 노드에서

# hostnamectl set-hostname worker2    // worker2 노드에서

# vi /etc/hosts

127.0.0.1 localhost
10.101.0.5 master
10.101.0.10 worker1
10.101.0.12 worker2

 

CRI-O 는 설치할 Kubernetes 버전과 동일한 버전으로 설치합니다.

(모든 노드에서)

# OS=xUbuntu_22.04
# VERSION=1.28

 

# echo "deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/$OS/ /" > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
# echo "deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/$VERSION/$OS/ /" > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable:cri-o:$VERSION.list

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

# apt -y update

# apt -y upgrade    // 설치중 묻는 질문에 기본값으로 답변

# apt -y install cri-o cri-o-runc cri-tools    // 설치중 묻는 질문에 기본값으로 답변

# systemctl enable --now crio

 

설치를 잘 마쳤으면 CRI-O 버전이 확인됩니다.

# crio version
crio version 1.28.0
Version:        1.28.0
GitCommit:      unknown
GitCommitDate:  unknown
GitTreeState:   clean
BuildDate:      2023-08-28T05:59:01Z
GoVersion:      go1.19
Compiler:       gc
Platform:       linux/amd64
Linkmode:       dynamic

...

 

 

2. Kubernetes 설치

 

Kubernetes 공식 홈페이지 : https://kubernetes.io

 

(모든 노드에서)

kubelet 사용을 위해 swap 을 반드시 비활성화 시켜줍니다.

# swapoff -a

# cat /etc/fstab

fstab 에서도 swap 파티션이 존재한다면 주석처리하여 비활성화 시킵니다.

 

이제 kubeadm, kubelet, kubectl 를 설치해야 하는데, 이 세가지는 모두 Kubernetes 클러스터 관리와 상호 작용을 위한 도구입니다.
- kubeadm : 클러스터를 부트스트랩하는 명령
- kubelet : 클러스터의 모든 노드에서 실행되는 POD와 컨테이너 시작과 같은 작업을 수행하는 컴포넌트
- kubectl : 클러스터와 통신하기 위한 CLI 유틸리티

 

패키지 저장소에서 파일을 안전하게 다운로드 받기 위해 아래 패키지를 설치합니다.

# apt -y install apt-transport-https ca-certificates

 

현재 기준 Kubernetes 최신 버전인 1.28 버전의 공용 서명 키를 다운로드합니다.

# curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.28/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg

 

Kubernetes Repository 를 추가합니다.

# echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.28/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list

 

APT 패키지 인덱스를 업데이트하고 kubelet, kubeadm, kubectl 을 설치합니다.

그리고 패키지가 자동으로 버전업 되지 않도록 고정합니다.

# apt -y update
# apt -y install kubelet kubeadm kubectl    // 설치중 묻는 질문에 기본값으로 답변
# apt-mark hold kubelet kubeadm kubectl

 

커널에 필요한 모듈을 로드 합니다.

(모든 노드에서)

# modprobe overlay
# modprobe br_netfilter

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

 

sysctl 파라메타 값을 설정하고 리부팅 없이 적용합니다.
# 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
# sysctl --system

 

CRI-O는 기본적으로 systemd 라는 cgroup 드라이버를 사용합니다. 

(모든 노드에서)

# cat <<EOF | sudo tee /etc/crio/crio.conf.d/02-cgroup-manager.conf
[crio.runtime]
conmon_cgroup = "pod"
cgroup_manager = "systemd"
EOF

 

 

3. Cluster 생성

 

서버간 통신할 사설 네트워크 대역을 설정합니다.

현재 노드와 중복되지 않도록 새로운 대역으로 설정해 주었습니다.

- Nodes network : 10.101.0.0/24

- Pods network : 10.101.1.0/24

쿠버네티스 구성에 필요한 이미지를 다운로드 받아야 하므로 이 단계에서 시간이 약간 소요됩니다.

(master 노드에서)

# kubeadm init --pod-network-cidr=10.101.1.0/24

 

아래는 쿠버네티스 컨트롤 플레인이 성공적으로 초기화 되었을때 출력하는 메세지 입니다.

Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

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

Alternatively, if you are the root user, you can run:

  export KUBECONFIG=/etc/kubernetes/admin.conf

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join 10.101.0.5:6443 --token w6ioaq.l37qcxuvs98q4n02 \
--discovery-token-ca-cert-hash sha256:bddfcfabe16f76edbb6a8af08a835ebf9defc67d902dd02091174e1bccacaa76

 

위에 나와있는 안내 대로 추가 명령을 실행하는데, 현재는 root 상태이므로 아래명령으로 Kubernetes 사용자 환경을 로드 합니다.

일반 사용자 상태로 진행을 원할 경우 위 안내된 mkdir 부분부터 세줄 명령을 실행하면 됩니다.

(master 노드에서)
# export KUBECONFIG=/etc/kubernetes/admin.conf

 

앞으로 SSH 접속시마다 자동으로 환경이 로드 되도록 하면 편리합니다.

# echo 'export KUBECONFIG="/etc/kubernetes/admin.conf"' >> ~/.bashrc

 

master 노드에서 확인 가능한 노드 상태를 출력합니다.

# kubectl get nodes
NAME     STATUS   ROLES           AGE   VERSION
master   Ready    control-plane   39s   v1.28.1

 

worker 노드에서는 아래와 같이 master 서버에 join (가입) 합니다.

token 과 hash 값은 쿠버네티스 컨트롤 플레인이 초기화 되었을때 출력된 값으로 합니다.

 

(모든 worker 노드에서)

# kubeadm join 10.101.0.5:6443 --token w6ioaq.l37qcxuvs98q4n02 \
--discovery-token-ca-cert-hash sha256:bddfcfabe16f76edbb6a8af08a835ebf9defc67d902dd02091174e1bccacaa76

 

다시 master 노드에서 확인 가능한 노드 상태를 출력하면 가입된 worker 노드 리스트까지 확인이 됩니다.

ROLES 부분이 아래와 같이 출력 되었는지 확인합니다.

(master 노드에서)

# kubectl get nodes
NAME      STATUS   ROLES           AGE     VERSION
master    Ready    control-plane   2m24s   v1.28.1
worker1   Ready    <none>          88s     v1.28.1
worker2   Ready    <none>          81s     v1.28.1

 

 

[참고 : Cluster 삭제]

 

이번에는 Cluster 를 삭제하는 방법을 안내합니다.

계속 Cluster 구성 진행을 원하시는 분은 이 부분을 건너뛰면 되고, 구성이 꼬이거나 처음부터 다시 하실 분만 참고하시면 됩니다.

 

(master 노드에서)

# kubeadm reset

# rm -r /etc/cni/net.d/*
# systemctl restart kubelet

 

(모든 worker 노드에서)

kubeadm join 명령을 하기 전에 아래 명령으로 기존 Cluster 정보를 삭제해야 합니다.

# kubeadm reset

# rm -rf /etc/kubernetes/*

# systemctl stop kubelet

 

 

4. Calico 설치

 

Calico 공식 홈페이지 : https://www.tigera.io/project-calico

 

Project Calico 는 Kubernetes에 대한 네트워크 정책 엔진입니다.
Calico 네트워크 정책 집행을 통해 네트워크 세분화 및 테넌트 격리를 구현할 수 있습니다.

 

1) Calico 설치하기

(master 노드에서)

Tigera Calico 연산자 및 사용자 지정 리소스 정의를 설치합니다.

현재 기준 Calico 최신버전은 3.26.1 입니다.
# kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/tigera-operator.yaml

필요한 커스텀 리소스를 생성하여 Calico 를 설치합니다.

배포하는 yaml 파일에서 CIDR 정보를 자신이 사용하는 네트워크 정보로 수정하고 생성합니다.

# wget https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/custom-resources.yaml

# sed -i 's/192.168.0.0\/16/10.101.1.0\/24/' custom-resources.yaml 

# kubectl create -f custom-resources.yaml

다음 명령을 사용하여 모든 Pod 가 실행 중인지 확인합니다.

이 부분에서 모든 STATUS 값이 Running 이 되기까지 약간의 시간이 소요됩니다.

# kubectl get pods -n calico-system
NAME                                       READY   STATUS    RESTARTS   AGE
calico-kube-controllers-7fd8984cb7-b5t6n   1/1     Running   0          2m37s
calico-node-74bjg                          1/1     Running   0          2m37s
calico-node-8mrfw                          1/1     Running   0          2m37s
calico-node-9xn6h                          1/1     Running   0          2m37s
calico-typha-d4c4b7984-l4p5j               1/1     Running   0          2m37s
calico-typha-d4c4b7984-lc9hm               1/1     Running   0          2m31s
csi-node-driver-9lmnz                      2/2     Running   0          2m37s
csi-node-driver-hzt8h                      2/2     Running   0          2m37s
csi-node-driver-ljsds                      2/2     Running   0          2m37s

 

 

5. 애플리케이션 배포

 

볼륨을 포함한 애플리케이션을 배포하고 외부에서 접근하기 위한 네트워크 설정 및 도메인 연결 예제입니다.

 

1) Namespace

애플리케이션을 생성하고 배포할 작업공간을 생성하고 현재의 공간으로 변경해줍니다.

(master 노드에서)

# kubectl create ns sysdocu

# kubectl config set-context --current --namespace=sysdocu

 

2) Volume 생성

NFS, GlusterFS, Ceph 등 별도의 서버를 미리 구성하고 해당 공간을 할당받기 위해

PV (Persistent Volume) 와 PVC (Persistent Volume Claim) 를 생성하는 방법도 있지만,

여기에서는 Pod 가 배포된 worker 노드의 공간을 할애하는 hostPath 방법으로 진행해 보겠습니다.

hostPath 를 사용할 경우 디렉토리를 지정하는 것 외에 별도 작업은 없습니다.

html 데이터를 저장할 디렉토리를 생성합니다.

(모든 worker 노드에서)

# mkdir /html

 

3) Deployment 생성

Deployment 를 사용하면 Pod 생성 및 여러가지 옵션을 추가하여 다양한 구성이 가능합니다.

Deployment yaml 파일을 작성합니다.

(master 노드에서)

# vi deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:latest
          ports:
            - containerPort: 80
          volumeMounts:
            - name: html-volume
              mountPath: /html/user001
      volumes:
        - name: html-volume
          hostPath:
            path: /usr/share/nginx/html
            type: DirectoryOrCreate

 

작성한 yaml 파일을 적용하여 생성합니다.

# kubectl apply -f deployment.yaml

deployment.apps/nginx-deployment created

 

Pod 가 자동 생성되는데, 아래와 같이 확인이 가능합니다.

# kubectl get pods
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-694db9fb84-b5h2r   1/1     Running   0          20s

 

4) Service 생성

네트워크 접근이 가능하도록 Service 를 생성해 줍니다.

테스트 목적이긴 하지만 외부 네트워크에서 접근이 되도록 해보겠습니다.

Service yaml 파일을 작성합니다.

# vi service.yaml

apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  selector:
    app: nginx
  type: NodePort
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
      nodePort: 30080  # 여기에 원하는 NodePort 값을 지정하세요. (범위 : 30000~32767)

 

* 참고

Service 에서 생성할 type 은 ClusterIP, NodePort, LoadBalancer 가 있습니다.

- ClusterIP : 클러스터 내부 통신만 가능한 IP

- NodePort : worker 노드의 IP 와 지정한 포트 (30000~32767 로 제한) 를 이용해 Pod 에 연결 가능

- LoadBalancer : 별도의 공인 IP 가 할당되고, 포트를 마음대로 사용 가능 (베어메탈 환경에서는 MetalLB 를 설치 필요)

 

작성한 yaml 파일을 적용하여 생성합니다.

# kubectl apply -f service.yaml

service/nginx created

 

Service 생성시 Endpoint 도 같이 생성되는데, 두가지 정보를 함께 출력해보면 아래와 같습니다.

# kubectl get services,ep

NAME    TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
nginx   NodePort   10.110.222.108   <none>        80:30080/TCP   17s


NAME    ENDPOINTS        AGE
nginx   10.101.1.66:80   17s

 

외부 네트워크에서 접근되는지 확인합니다.

접근할 IP 는 Pod 가 위치하는 worker 노드인데, 아래 명령으로 확인 가능합니다.

# kubectl get pod -o wide

NAME                                READY   STATUS    RESTARTS   AGE     IP            NODE      NOMINATED NODE   READINESS GATES
nginx-deployment-694db9fb84-b5h2r   1/1     Running   0          7m22s   10.101.1.66   worker2   <none>           <none>

 

worker2 노드인것을 확인하였으며, 외부에서 worker2 노드의 공인 IP 와 위에서 설정한 포트 30080 으로 접근시 nginx 초기페이지가 출력되는것이 확인됩니다. 예제에서는 worker2 노드의 공인 IP 로 연결하였지만 실제로는 꼭 worker2 노드의 공인 IP 로 할 필요는 없습니다. NodePort 의 경우 master 또는 어떤 worker 노드로 연결하던 설정한 Pod 로 연결됩니다.

# curl 115.68.249.176:30080

 

5) Ingress 생성

Ingress 를 사용하면 도메인 연결이 가능합니다.

Ingress yaml 파일을 작성합니다.

# ingress.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx
  namespace: sysdocu
spec:
  rules:
  - host: nginx.sysdocu.kr    # 사용할 도메인
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginx    # 연결할 Service 이름
            port:
              number: 80    # 연결할 Service 포트 번호

 

작성한 yaml 파일을 적용합니다.

# ingress.networking.k8s.io/nginx created

 

Ingress 가 생성되었습니다.

# kubectl get ingress
NAME    CLASS    HOSTS              ADDRESS   PORTS   AGE
nginx   <none>   nginx.sysdocu.kr             80      30s

 

사용할 도메인 (nginx.sysdocu.kr) 은 DNS 에서 IP 를 worker 노드의 IP 로 미리 등록해 놓아야 합니다.

아래와 같이 접속이 확인되었습니다.

# curl nginx.sysdocu.kr:30080

 

nginx 와 같은 웹서버에서 사용하는 포트는 보통 80 또는 443 이지만, NodePort 사용시 번거롭게 30000~32767 사이의 포트 번호를 사용해야 연결이 됩니다. 포트 번호없이 도메인만으로 접속을 원하는 경우 MetalLB 를 구성해 공인 IP 를 할당해 주면 됩니다.

- MetalLB 설치 : https://sysdocu.tistory.com/1854

 

 

 

 

반응형

댓글()

Docker 컨테이너 생성하지 않고 이미지 쉘에 접근하기

반응형

Docker 이미지를 다운로드 받거나 아직 받지 않은 상태에서도 이미지명만 알고 있으면 쉘 접속이 가능합니다.

방법은 아래와 같습니다.

 

현재 다운로드 받은 이미지 확인

# docker images

docker.io/php                                                                  latest              3d07cacc45bb        8 days ago          485 MB

 

이미지 쉘 접속하기

예) docker run --rm -it <Docker 이미지명> sh

# docker run --rm -it docker.io/php sh

 

반응형

댓글()

4. Kubernetes 대시보드 설치

반응형

4. Kubernetes 대시보드 설치

 

1) 대시보드 설치 및 접근 허용 설정

 

Kubernetes 는 구성 현황 및 오브젝트들을 GUI 환경에서 볼 수 있도록 지원을 해줍니다.

 

(control 노드에서)

# kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.6.1/aio/deploy/recommended.yaml

 

대시보드 접근을 활성화 합니다.

아래 명령이후 쉘로 빠져나오지 않는데, ctrl + z 후 bg (백그라운드 명령) 로 돌려놓고 netstat 로 살펴보면

127.0.0.1 로만 접근이 허용되어 있는것이 보입니다.

# kubectl proxy

 

이제 다시 fg (포어그라운드 명령) 도 돌리고, ctrl + c 버튼으로 명령을 취소합니다.

어디에서든 접속이 가능하도록 하기 위해 아래 작업을 계속 진행합니다.

 

kubernetes-dashboard 네임스페이스의 서비스를 확인합니다.

# kubectl get services -n kubernetes-dashboard
NAME                        TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
dashboard-metrics-scraper   ClusterIP   10.102.90.181   <none>        8000/TCP   5m14s
kubernetes-dashboard        ClusterIP   10.105.198.81   <none>        443/TCP    5m14s

 

# kubectl edit services kubernetes-dashboard -n kubernetes-dashboard

...
spec:
  ...
  type: NodePort    // ClusterIP 를 NodePort 변경 후 입력후 저장 (반드시 :wq!)
...

 

접근 가능한 클러스터 IP 가 변경되었습니다.

# kubectl get services -n kubernetes-dashboard
NAME                        TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)         AGE
dashboard-metrics-scraper   ClusterIP   10.102.90.181   <none>        8000/TCP        17m
kubernetes-dashboard        NodePort    10.105.198.81   <none>        443:32085/TCP   17m

 

웹브라우저에서 컨트롤 노드의 IP 와 포트를 이용해 접근하는데, 꼭 https 프로토콜로 접근합니다.

https://<컨트롤노드IP>:32085

브라우저에 따라 '안전하지 않은 페이지' 로 표시될 수 있는데, 이는 인증서가 아직 없어서 그런 것이므로 그냥 접속하도록 합니다.

토큰 또는 Kubeconfig 둘중 하나의 로그인 방법을 선택해야 하는데, 여기서는 토큰으로 로그인 하는 방법으로 진행하겠습니다.

컨트롤 노드에서 토큰을 생성하기 위해 yaml 파일을 작성합니다.

 

2) 계정 생성 및 admin 권한 부여

 

계정을 생성하기 위해 yaml 파일을 아래 내용으로 만듭니다.

# vi dashboard-account.yaml

apiVersion: v1
kind: ServiceAccount
metadata:
  name: admin
  namespace: kubernetes-dashboard

 

계정을 생성합니다.

# kubectl create -f dashboard-account.yaml

 

계정 생성을 확인합니다. (sa : serviceaccount)

# kubectl get sa -n kubernetes-dashboard |grep admin
NAME                   SECRETS   AGE
admin                  0         10s

 

생성된 계정에 권한을 주기 위해 yaml 파일을 아래 내용으로 만듭니다.

# vi dashboard-role.yaml

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: admin
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: admin
  namespace: kube-system

 

권한을 적용합니다.

# kubectl create -f dashboard-role.yaml

 

적용된 권한을 확인합니다.

# kubectl get clusterrolebinding admin
NAME    ROLE                        AGE
admin   ClusterRole/cluster-admin   12m

이제 로그인에 필요한 계정의 token 을 출력합니다.

Kubernetes 1.24 버전 부터는 kubectl get 명령으로 token 이 확인 되지 않아 아래 내용으로 확인해야 합니다.

# kubectl create token admin -n kubernetes-dashboard
eyJhbGciOiJSUzI1NiIsImtpZCI6IktFTlFFRkt6ajZDX2VnV0NZNs93dWZ6TUhBVFBNY1RnUTBBZWVIa0dSeGcifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlem5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNjcyNzf1ODI0LCJpYXQiOjE2NzI3MjIyMeQsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLzxvY2FsIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOierdWJlcm5ldGVzLWRhc2hib2FyZCIsInNlcnZpY2VhY2NvdWe0Ijp7Im5hbWUiOiJhZG1pbiIsInVpZCI6IjAzYTJlZDAwLWI5ZDAtNDY5OC04NWE3LTE3MzU5ZDI5YzllMyJ9fSwibmJmIjowNjcyNzIyMjI0LCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZXJuZXRlcy1kYXNoYm9hcmQ6YWRtaW4ifQ.iN6W5bbpQRYNUoVss-Z6YtP83SaoG9m2Qe6-V41ypaWT6p12QTDhDEtOXAtP7j9o4Mwm-WrlM_rfqR9vw7F-BeWmfyfjZkCcpkE-sOzQ_NtmTL8OMzfnOmuxYhYnOdvzM8j66yTd8-osEqcQ023Tx1t7nQlbALUwu6G6p1kXx9mtMROnqkQRnr6_e89WejwaCsYC7k4WMs5NkA48Wselmrnww-kf5Fl-y3PFjhWjRIC-IU1nlZALBPBMwIKsTBFCt7RmhsrXD0UA7RacZog5U-eSeYJRKKGKzW7PmFXEwIIdFeCTWUYJOk4-Nn_nfyxe3Ismt7q8xbuh6XDCzmFYaQ

 

출력된 token 전체를 복사하여 웹브라우저의 로그인 화면 token 입력란에 넣고 [로그인] 버튼을 누르면 관리 페이지에 로그인 할 수 있습니다.

 

반응형

댓글()

3. Namespace 생성, LimitRange 를 이용한 자원 사용량 제한, POD 및 Deployment 생성, 자원 제한 확인

반응형

3. Namespace 생성, LimitRange 를 이용한 자원 사용량 제한, POD 및 Deployment 생성, 자원 제한 확인

 

1) Namespace 생성

 

test-ns 라는 이름의 네임스페이스를 만듭니다.

# kubectl create ns test-ns

 

생성된 네임스페이스를 확인합니다.

# kubectl get ns
NAME               STATUS   AGE
calico-apiserver   Active   19h
calico-system      Active   19h
default            Active   20h
kube-node-lease    Active   20h
kube-public        Active   20h
kube-system        Active   20h
test-ns            Active   2s
tigera-operator    Active   19h

 

2) LimitRange 설정

 

네임스페이스에 LimitRange 설정을 하기 위해 yaml 파일을 생성합니다.

# vi test-limitrange.yaml

apiVersion: v1
kind: LimitRange
metadata:
  name: test-limitrange
spec:
  limits:
  - default:  # 기본 제한값 (생략 가능)
      cpu: 1
      memory: 1Gi
    defaultRequest:  # 요청 제한 값 (생략 가능)
      cpu: 1
      memory: 1Gi
    max:  # 최대값 (생략 가능)
      cpu: 1
      memory: 1Gi
    min:  # 최소값 (생략 가능)
      cpu: 1
      memory: 500Mi
    type: Container

 

test-ns 네임스페이스에 적용 합니다.

# kubectl apply -f test-limitrange.yaml -n test-ns
limitrange/test-limitrange created

 

모든 네임스페이스에 설정된 LimitRange 목록을 확인 할 수 있습니다.

# kubectl get limitrange -n test-ns  // 네임스페이스 지정하여 보기

# kubectl get limitrange --all-namespaces                       // 네임스페이스 전체 보기
NAMESPACE        NAME              CREATED AT
test-ns                 test-limitrange   2022-12-29T02:08:54Z

 

자세한 LimitRange 정보를 보고 싶을땐 아래와 같이 실행합니다.

# kubectl get limitrange test-limitrange --output=yaml -n test-ns

 

3) POD 생성

 

httpd 이미지를 이용해 POD 를 생성합니다.

기존에 httpd 이미지를 받지 못하였을 경우 crictl 명령을 이용해 다운로드 합니다.

# crictl pull httpd

Image is up to date for docker.io/library/httpd@sha256:753edbf6bf19a74c580c57f7d98e05b6b34073adc929234da6eb193a8029ab91

 

POD 을 생성하기 위한 환경 파일을 만듭니다.

# vi test-httpd.yaml

apiVersion: v1
kind: Pod
metadata:
  name: test-httpd
spec:
  containers:
  - name: test-container
    image: httpd

 

test-ns 네임스페이스 POD 를 생성 합니다.  // yaml 파일을 이용해 POD 를 생성하는 방법

# kubectl apply -f test-httpd.yaml -n test-ns

pod/test-httpd created

 

생성된 POD 정보를 자세히 보고싶을 경우 아래와 같이 실행합니다.

# kubectl get pods test-httpd --output=yaml -n test-ns

 

* 참고

POD 를 생성 한 뒤 Namespace 에 LimitRange 를 적용할 경우 기존의 POD 에는 LimitRange 가 반영되지 않습니다.

 

* 참고 : 네임스페이스를 삭제하면 해당 Namespace 와 쿠버네티스 오브젝트들이 삭제되고, 할당되있던 리소스들이 자동으로 해제됩니다.

# kubectl delete ns test-ns
namespace "test-ns" deleted

 

4) Deployment 생성

 

한개의 httpd 컨테이너를 더 만들어 봅니다.

원래는 POD 생성후 Deployment 생성이 순서이지만 Deployment 생성시 POD 이 없다면 자동 생성됩니다.

우선 CRI-O 명령을 이용해 이미지를 다운로드 합니다.

 

httpd 이미지를 이용해 deployment 를 생성 합니다.  // 명령줄에서 POD를 생성, 배포하는 방법

                                                                                // POD 없이 deployment 하면 POD 자동 생성 후 배포가 됩니다.

자원 사용에 제한을 주기 위해 test-ns 라는 네임스페이스 안에 생성합니다.

# kubectl create deployment test-httpd2 --image httpd -n test-ns
deployment.apps/test-httpd2 created

 

test-ns 네임스페이스 내 POD 현황입니다.

생성된 POD 는 두 개가 보입니다.

# kubectl get pods -n test-ns
NAME                           READY   STATUS    RESTARTS   AGE
test-httpd                       1/1     Running   0          12m
test-httpd2-7c7c8bd5d-x4jl5       1/1    Running   0          3m55s  // 자동 생성이라 이름에 난수값이 들어감

 

test-ns 네임스페이스 내 배포 현황입니다.

배포된 컨테이너는 한 개라서 test-httpd2 만 보입니다.

# kubectl get deployments -n test-ns
NAME          READY   UP-TO-DATE   AVAILABLE   AGE
test-httpd2        1/1     1            1           45s

 

5) LimitRange 적용 확인 (부하 테스트)

 

이제 httpd 컨테이너 쉘에 접근하여 부하를 주면, control 노드에서 확인되는 부하는

위에서 제한한 LimitRange 한도로 제한되는것을 확인 할 수 있습니다.

# kubectl exec -it test-httpd -n test-ns -- bash    // httpd 컨테이너 쉘 접근

# apt -y update

# apt install stress    // 부하 테스트 패키지 설치 후

# cat /proc/cpuinfo |grep processor |wc -l    // 서버의 코어수 확인

# stress -c 2    // CPU 부하 시작

 

다른 터미널 창을 띄워 control-node 에서 컨테이너별 자원 사용량 체크 툴을 설치합니다.

# git clone https://github.com/kodekloudhub/kubernetes-metrics-server.git
# cd kubernetes-metrics-server
# kubectl create -f .

 

# kubectl top pod -n test-ns
NAME                           CPU(cores)   MEMORY(bytes)   
test-httpd                     1000m        24Mi    // 1000m 은 1core 를 의미합니다.
test-httpd2-7c7c8bd5d-x4jl5   1m           0Mi             

 

컨테이너에서 stress 테스트를 중지했을때

# kubectl top pod -n test-ns
NAME                           CPU(cores)   MEMORY(bytes)   
test-httpd                     1m           23Mi            
test-httpd2-7c7c8bd5d-x4jl5   1m           0Mi  

 

참고로 노드별 자원 사용량도 확인이 가능합니다.

# kubectl top node -n test-ns
NAME           CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%   
control-node   85m          4%     1759Mi          46%       
work-node-1    27m          1%     1200Mi          31%       
work-node-2    39m          1%     1273Mi          33%     

 

반응형

댓글()

2. CRI-O 와 Kubernetes 를 활용한 httpd 배포

반응형

2. CRI-O 와 Kubernetes 를 활용한 httpd 배포

 

1) httpd 설치

 

(control 노드에서)

httpd 이미지를 배포합니다.

# kubectl create deployment httpd --image=httpd
deployment.apps/httpd created

 

배포 명령 이후 진행상태가 이벤트 로그에 기록되므로 아래와 같이 출력해 볼 수 있습니다.

# kubectl get events |grep httpd
70s         Normal   Scheduled           pod/httpd-975f8444c-5xfch     Successfully assigned default/httpd-975f8444c-5xfch to sysdocu-189114
70s         Normal   Pulling             pod/httpd-975f8444c-5xfch     Pulling image "httpd"
58s         Normal   Pulled              pod/httpd-975f8444c-5xfch     Successfully pulled image "httpd" in 11.734922345s (11.734929076s including waiting)
58s         Normal   Created             pod/httpd-975f8444c-5xfch     Created container httpd
58s         Normal   Started             pod/httpd-975f8444c-5xfch     Started container httpd
70s         Normal   SuccessfulCreate    replicaset/httpd-975f8444c    Created pod: httpd-975f8444c-5xfch
70s         Normal   ScalingReplicaSet   deployment/httpd              Scaled up replica set httpd-975f8444c to 1

 

httpd 배포 정보를 확인합니다.

# kubectl describe deployment httpd

 

2) yaml 파일 생성 및 배포

 

httpd 리소스 템플릿 파일을 생성합니다.

# kubectl get deployment httpd -o yaml > httpd.yaml

 

생성된 httpd.yaml 파일을 열어 포트를 추가합니다.

# vi httpd.yaml

...
    spec:
      containers:
      - image: httpd
        imagePullPolicy: Always
        name: httpd
        ports:
        - containerPort: 80
          protocol: TCP
        resources: {}
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
...

 

수정된 yml 파일을 기본 httpd 템플릿으로 갱신 (over write) 합니다.

# kubectl replace -f httpd.yaml

deployment.apps/httpd replaced

 

갱신 시간으로 이미지 업데이트 내역을 확인 할 수 있습니다.

# kubectl get deployment
NAME    READY   UP-TO-DATE   AVAILABLE   AGE
httpd   1/1     1            1           11m

 

# kubectl expose deployment/httpd
service/httpd exposed

 

클러스터 httpd 서비스 IP 를 출력합니다.

# kubectl get svc httpd
NAME    TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)   AGE
httpd   ClusterIP   10.99.72.96   <none>        80/TCP    5m24s

 

출력된 클러스터 IP 로 httpd 접근 확인이 가능합니다.

# curl 10.99.72.96:80
<html><body><h1>It works!</h1></body></html>

엔드포인트 httpd 서비스 IP 출력합니다.

# kubectl get ep httpd
NAME    ENDPOINTS         AGE
httpd   10.101.0.195:80   5m51s

 

출력된 엔드포인트 IP 로 httpd 접근 확인이 가능합니다.

# curl 10.101.0.195:80

<html><body><h1>It works!</h1></body></html>

 

3) httpd 스케일 아웃 (Replica)

 

httpd 의 replica 를 3으로 조정하면 3개의 POD 가 생성된 것을 확인 할 수 있습니다.

# kubectl scale deployment httpd --replicas=3
deployment.apps/httpd scaled

 

복제되는 과정에서 시간이 약간 걸리며 watch 명령으로 모니터링을 해보면 아래와 같이 Ready 와 AVAILABLE 값이 3까지 늘어나는 것이 보입니다.

# watch kubectl get deployment httpd
NAME    READY   UP-TO-DATE   AVAILABLE   AGE
httpd   3/3     3            3           15h

 

엔드포인트도 POD 개수대로 늘어난 것을 확인할 수 있습니다.

# kubectl get ep httpd
NAME    ENDPOINTS                                        AGE
httpd   10.101.0.129:80,10.101.0.195:80,10.101.0.67:80   41m

 

이제는 POD 를 삭제해도 replica 개수 3 으로 유지 (자동 생성) 됩니다.

클러스터 IP 로 접근을 해보면 3개의 POD 로 분산되어 접근되는 것을 확인할 수 있습니다.

 

4) 클러스터 외부에서 접근 허용 설정

 

현재의 POD 정보 입니다.

# kubectl get pods
NAME                     READY   STATUS    RESTARTS   AGE
httpd-56b65865c4-74zxp   1/1     Running   0          15h
httpd-56b65865c4-b8phd   1/1     Running   0          10m
httpd-56b65865c4-dkjdc   1/1     Running   0          10m

 

NAME 값을 이용하여 POD 의 환경 설정값을 확인합니다.

# kubectl exec httpd-56b65865c4-74zxp -- printenv |grep KUBERNETES
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
KUBERNETES_SERVICE_HOST=10.96.0.1
KUBERNETES_SERVICE_PORT=443
KUBERNETES_SERVICE_PORT_HTTPS=443

 

현재의 서비스 정보 입니다.

# kubectl get svc
NAME         TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)   AGE
httpd        ClusterIP   10.99.72.96   <none>        80/TCP    51m
kubernetes   ClusterIP   10.96.0.1     <none>        443/TCP   18h

 

외부에서 접근이 가능하도록 svc 값을 삭제하고 LoadBalancer 형태로 다시 생성해 줍니다.

# kubectl delete svc httpd
service "httpd" deleted


# kubectl expose deployment httpd --type=LoadBalancer
service/httpd exposed

 

다시 svc 정보를 출력해보면 httpd 가 LoadBalancer 형태로 생성되었으며, EXTERNAL-IP 는 없는 상태입니다.

# kubectl get svc
NAME         TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
httpd        LoadBalancer   10.96.23.114   <pending>     80:31452/TCP   2m29s
kubernetes   ClusterIP      10.96.0.1      <none>        443/TCP        18h

 

웹브라우저를 통해 새로 생성된 포트로 접근을 해보면 httpd 초기 페이지가 출력되며, 3개의 POD 로 분산 접근이 됩니다.

http://<서버 공인 IP>:31452

 

[참조] https://blog.psnote.co.kr/184

 

 

반응형

댓글()

1. Ubuntu 22.04 에서 CRI-O, Kubernetes 1.26, Calico 설치하기

반응형

Kubernetes 는 컨테이너의 생성, 배포, 실행을 하는 등 컨테이너를 관리하는 오픈소스 플랫폼 입니다.

여기에서는 Ubuntu 22.04 버전의 서버 3대로 (master 노드 1대 / worker 노드 2대) Kubernetes 를 구성하는 방법에 대해 설명합니다.

 

 

1. CRI-O 설치

 

CRI-O 공식 홈페이지 : https://cri-o.io

 

설치에 앞서 사용하고자 하는 호스트네임을 적용 합니다.

# hostnamectl set-hostname master      // master 노드에서

# hostnamectl set-hostname worker1    // worker1 노드에서

# hostnamectl set-hostname worker2    // worker2 노드에서

 

(모든 노드에서)

# vi /etc/hosts

127.0.0.1 localhost
10.101.0.5 master
10.101.0.10 worker1
10.101.0.12 worker2

 

운영 할 Kubernetes 버전이 1.26인 경우 CRI-O 버전 1.26을 설치해야 합니다.

# OS=xUbuntu_22.04
# VERSION=1.26

 

# echo "deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/$OS/ /" > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
# echo "deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/$VERSION/$OS/ /" > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable:cri-o:$VERSION.list

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

# apt -y update

# apt -y upgrade  // 업그레이드 완료 후 최신 커널로 사용하고자 할 경우 reboot 을 진행합니다.

# apt -y install cri-o cri-o-runc cri-tools

 

CRI-O 를 실행하고 버전을 확인합니다.

# systemctl enable --now crio

# crio --version

crio version 1.26.4
Version:        1.26.4
GitCommit:      unknown
GitCommitDate:  unknown
GitTreeState:   clean
BuildDate:      2023-08-17T06:08:14Z
GoVersion:      go1.19
Compiler:       gc
Platform:       linux/amd64
Linkmode:       dynamic

...

 

2. Kubernetes 설치

 

Kubernetes 공식 홈페이지 : https://kubernetes.io

 

설치 전, 쿠버네티스 (kubelet) 사용을 위해 SWAP 을 반드시 비활성화 시켜줍니다.

# swapoff -a

# cat /etc/fstab

fstab 에서도 swap 파티션이 존재한다면 주석처리하여 비활성화 시킵니다.

 

1) kubeadm, kubelet 및 kubectl 설치

다음 패키지들을 설치합니다.
- kubeadm : 클러스터를 부트스트랩하는 명령
- kubelet : 클러스터의 모든 노드에서 실행되는 POD와 컨테이너 시작과 같은 작업을 수행하는 컴포넌트
- kubectl : 클러스터와 통신하기 위한 CLI 유틸리티

 

(모든 노드에서)

# apt -y install apt-transport-https ca-certificates
# curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add
# echo "deb https://apt.kubernetes.io/ " >> ~/kubernetes.list
# mv ~/kubernetes.list /etc/apt/sources.list.d
# apt-y update
# VERSION="1.26.0-00"
# apt -y install kubelet=$VERSION kubeadm=$VERSION kubectl=$VERSION kubernetes-cni

 

쿠버네티스는 버전이 중요하므로 패키지가 자동으로 설치, 업그레이드 또는 제거되지 않도록 고정 시킵니다.

# apt-mark hold kubelet kubeadm kubectl

kubelet set on hold.
kubeadm set on hold.
kubectl set on hold.

 

2) 쿠버네티스 필수 환경 구성

(모든 노드에서)

쿠버네티스 운영을 위해 필요한 필수 요소들을 설치하고 구성합니다.

필요한 모듈을 로드하고 부팅시에도 자동 적용되도록 합니다.
# modprobe overlay
# modprobe br_netfilter

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

 

IPv4 를 포워딩하여 iptables 가 브릿지된 트래픽을 보게 합니다.

sysctl 파라미터를 설정하면, 재부팅 후에도 값이 유지됩니다.
# 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

재부팅하지 않고 sysctl 파라미터를 적용합니다.
# sysctl --system

3) cgroup 드라이버 설정
(모든 노드에서)
CRI-O는 기본적으로 systemd 라는 cgroup 드라이버를 사용합니다. 
# cat <<EOF | sudo tee /etc/crio/crio.conf.d/02-cgroup-manager.conf
[crio.runtime]
conmon_cgroup = "pod"
cgroup_manager = "systemd"
EOF

 

4) master 서버 초기화 및 노드 연결

(master 노드에서)

서버간 통신할 사설 네트워크 대역을 설정합니다.

쿠버네티스 구성에 필요한 이미지를 다운로드 받아야 하므로 이 단계에서 시간이 약간 소요됩니다.

# kubeadm init --pod-network-cidr=10.101.0.0/24

 

아래는 쿠버네티스 컨트롤 플레인이 성공적으로 초기화 되었을때 출력하는 메세지 입니다.

Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

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

Alternatively, if you are the root user, you can run:

  export KUBECONFIG=/etc/kubernetes/admin.conf

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join 10.101.0.5:6443 --token fayi8m.4qus4e8y3cnon9nc \
--discovery-token-ca-cert-hash sha256:b5693e9d1a3fd79b64e790d5218369ef9449b211c0c30eef88e6376887ad774b 

 

위에 나와있는 안내 대로 추가 명령을 실행합니다.

클러스터 사용을 시작하려면 일반 사용자로 다음을 실행해야 합니다.

 

(master 노드에서)
# mkdir -p $HOME/.kube
# sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
# sudo chown $(id -u):$(id -g) $HOME/.kube/config

또는 root 사용자인 경우 다음을 실행할 수 있습니다.
# export KUBECONFIG=/etc/kubernetes/admin.conf

 

앞으로 SSH 접속시마다 자동으로 환경이 로드 되도록 하면 편리합니다.

# echo 'export KUBECONFIG="/etc/kubernetes/admin.conf"' >> ~/.bashrc

 

master 노드에서 확인 가능한 노드 상태를 출력합니다.

STATUS 에서 NotReady 로 표시되지만, 아래에서 별도 작업을 통해 Ready 로 변경할 예정입니다.

# kubectl get nodes
NAME           STATUS     ROLES           AGE     VERSION
master             NotReady   control-plane   4m57s   v1.26.0

 

worker 노드에서는 아래와 같이 master 서버에 join (가입) 합니다.

token 과 hash 값은 쿠버네티스 컨트롤 플레인이 초기화 되었을때 출력된 값으로 합니다.

 

(worker 노드에서)

# kubeadm join 10.101.0.5:6443 --token fayi8m.4qus4e8y3cnon9nc \
--discovery-token-ca-cert-hash sha256:b5693e9d1a3fd79b64e790d5218369ef9449b211c0c30eef88e6376887ad774b

 

다시 master 노드에서 확인 가능한 노드 상태를 출력하면 가입된 worker 노드 리스트까지 확인이 됩니다.

(master 노드에서)

# kubectl get node
NAME           STATUS     ROLES           AGE    VERSION
master             NotReady   control-plane   8m1s   v1.26.0
worker1           NotReady   <none>          18s    v1.26.0
worker2           NotReady   <none>          16s    v1.26.0

 

 

3. Calico 설치하기

 

Project Calico 는 Kubernetes에 대한 네트워크 정책 엔진입니다.
Calico 네트워크 정책 집행을 통해 네트워크 세분화 및 테넌트 격리를 구현할 수 있습니다.

Calico 공식 홈페이지 : https://www.tigera.io/project-calico

 

1) Calico 설치하기

(master 노드에서)

Tigera Calico 연산자 및 사용자 지정 리소스 정의를 설치합니다.
# kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.24.5/manifests/tigera-operator.yaml

필요한 커스텀 리소스를 생성하여 Calico를 설치합니다.

배포하는 yaml 파일에서 CIDR 정보를 자신이 사용하는 네트워크 정보로 수정하고 생성합니다.

# wget https://raw.githubusercontent.com/projectcalico/calico/v3.24.5/manifests/custom-resources.yaml

# sed -i 's/192.168.0.0\/16/10.101.0.0\/24/' custom-resources.yaml 

# kubectl create -f custom-resources.yaml

다음 명령을 사용하여 모든 POD가 실행 중인지 확인합니다.

이 부분에서 모든 STATUS 값이 Running 이 되기까지 약간의 시간이 소요됩니다.

# watch kubectl get pods -n calico-system

NAME                                       READY   STATUS    RESTARTS   AGE
calico-kube-controllers-67df98bdc8-kdt6m   1/1     Running   0          83s
calico-node-hp78g                          1/1     Running   0          83s
calico-node-ntfq4                          1/1     Running   0          83s
calico-node-rwm2s                          1/1     Running   0          83s
calico-typha-7f4f4655f7-6psfv              1/1     Running   0          76s
calico-typha-7f4f4655f7-t7ccr              1/1     Running   0          83s

 

master 노드에서 POD 를 스케쥴링 할 수 있도록 모든 노드의 taint 를 제거 합니다.

우선 taint 상태를 확인하면 아래와 같이 출력되는데,

이 룰을 없애줘야 kubectl get node 명령으로 출력된 NotReady 상태가 Ready 상태로 변경됩니다.

# kubectl describe nodes |grep -i taint
Taints:             node-role.kubernetes.io/control-plane:NoSchedule
Taints:             <none>
Taints:             <none>

 

룰 뒤에 - 를 붙이면 제거됩니다.

# kubectl taint nodes master node-role.kubernetes.io/control-plane:NoSchedule-

 

taint 상태를 다시 확인합니다.

# kubectl describe nodes |grep -i taint

Taints:             <none>
Taints:             <none>
Taints:             <none>

 

이제 모든 노드의 상태가 Ready 로 돌아왔습니다.
# kubectl get nodes
NAME            STATUS   ROLES           AGE   VERSION
master                Ready    control-plane   36m   v1.26.0
worker1              Ready              14m   v1.26.0
worker2              Ready              12m   v1.26.0

 

* 참고

worker 노드는 사용 설정에 따라 <none> 이 아닐 경우 NoSchedule 이나 NoExecute 가 있을 수 있는데

제거해야하는 상황에 명령어가 수행되지 않는다면 아래와 같이 worker 노드에서 생성되었던 파일 2개 삭제 및 kubelet 데몬 중지 후 다시 join 을 하면 해결됩니다.

(해당 worker 노드에서)

# rm -f /etc/kubernetes/kubelet.conf
# rm -f /etc/kubernetes/pki/ca.crt 
# systemctl stop kubelet

# kubeadm join 10.101.0.5:6443 --token fayi8m.4qus4e8y3cnon9nc \
--discovery-token-ca-cert-hash sha256:b5693e9d1a3fd79b64e790d5218369ef9449b211c0c30eef88e6376887ad774b

 

반응형

댓글()

6. Docker PHPMyAdmin 설치

반응형

6. Docker PHPMyAdmin 설치

 

1) 설치 및 설정

 

접속할 MySQL 이 설치되어 있다는 가정하에 진행합니다. (Docker MySQL 설치)

최신버전의 PHPMyAdmin 이미지를 다운로드 받습니다.

# docker pull phpmyadmin:latest

 

phpmyadmin 컨테이너 환경 설정을 합니다.

# vi docker-compose.yml

...
    phpmyadmin:
        image: phpmyadmin:latest
        container_name: phpmyadmin
        restart: unless-stopped
        ports:
            - "8080:80"
        environment:
            PMA_ARBITRARY: 1

 

phpmyadmin 컨테이너를 가동 합니다.

# docker compose up -d phpmyadmin

 

2) PHPMyAdmin 페이지 접근 및 설정

 

웹브라우저로 관리 페이지에 접근합니다.

예) http://sysdocu.tistory.com:8080

 

입력란은 아래의 데이터로 입력 합니다.

서버 : mysql          // mysql 컨테이너 이름

사용자명 : root       // mysql 계정 이름

암호 : 12345678    // mysql 계정 패스워드

* mysql 컨테이너 입장에서는 로컬 접근이 아닌, 원격 접근 (호스트 서버 또는 다른 컨테이너) 이므로 접근권한이 없다면 추가해줘야 합니다.

 

 

 

반응형

댓글()

5. Docker 이미지 생성 (컨테이너 현재 상태 저장)

반응형

5. Docker 이미지 생성 (컨테이너 현재 상태 저장)

 

php 컨테이너의 경우 라이브러리 등을 추가 설치하고 docker compose down 및 up -d 명령을 사용하여 컨테이너를 재가동 하면

컨테이너에 설치한 라이브러리 파일이 초기화 되어져 다시 라이브러리를 설치하고 php 컨테이너를 재시작 해주어야 합니다.

이런 번거로움을 줄이기 위해서 라이브러리 설치 후 아래와 같이 컨테이너의 마지막 상태를 이미지로 저장할 수 있습니다.

 

실행중인 php 컨테이너를 중지합니다.

# docker compose stop php

중지한 php 컨테이너의 ID 를 확인 합니다.

# docker ps -a |grep php |awk {'print $1'}
891757604a66

중지한 컨테이너 ID 값을 이용하여 새로운 이미지를 만듭니다.

# docker commit 891757604a66 php:8.2.0-fpm_update1
sha256:1e7354a1a3030c6cf7e842f200bb3c9319e99fc700f68f8b363410b5a8e48c64

 

생성된 이미지 리스트를 확인합니다.

# docker images
REPOSITORY   TAG                 IMAGE ID       CREATED          SIZE
php          8.2.0-fpm_update1   1e7354a1a303   11 minutes ago   450MB
php          8.2.0-fpm           51dbab2b7efc   13 days ago      450MB
mysql        8.0.31              7484689f290f   2 weeks ago      538MB
httpd        2.4.54              157dcdf23d6c   2 weeks ago      145MB


다음 php 컨테이너를 생성할때 새로운 이미지 기반으로 생성하도록 합니다.

# vi docker-compose.yml

...
    php:
        image: php:8.2.0-fpm_update1
...


이제 php 컨테이너를 삭제 해도 이미지 기반으로 생성 및 구동할때, 이미 이전에 설치한 라이브러리가 있는것을 확인 할 수 있습니다.

 

반응형

댓글()

4. Docker PHP 환경 설정 및 MySQL 연동, 기타 라이브러리 활성화

반응형

4. Docker PHP 환경 설정하기 (php.ini)

 

1) PHP 환경 설정 방법

 

php 컨테이너 내의 설정 파일 (php.ini) 를 호스트 서버로 복사하고 호스트 서버의 php.ini 파일을 사용하도록 해야 합니다.

컨테이너가 구동중인 상태에서 아래와 같이 파일을 복사 합니다.

 

php 컨테이너의 /usr/local/etc/php/php.ini-development 파일을 /home/sysdocu/php/conf/ 디렉토리 아래에 php.ini 이름으로 복사.

# mkdir -p /home/sysdocu/php/conf

# docker cp php:/usr/local/etc/php/php.ini-development /home/sysdocu/php/conf/php.ini

 

기본적으로 소스내 PHP 태그없이도 코드 인식이 가능하도록하고 한국 표준시를 출력하도록 설정합니다.

# vi /home/sysdocu/php/conf/php.ini

short_open_tag = On
date.timezone = "Asia/Seoul"

 

호스트 서버에서 php.ini 파일을 사용할 수 있도록 docker-compose.yml 파일을 수정합니다.

# vi docker-compose.yml

...
    php:
        image: php:8.2.0-fpm
        container_name: php
        restart: unless-stopped
        ports:
            - "9000:9000"
        volumes:
            - /home/sysdocu/httpd/html:/var/www/html
            - /home/sysdocu/php/conf/php.ini:/usr/local/etc/php/php.ini
        command:
            - /bin/sh
            - -c
            - |
              echo "security.limit_extensions = .html .htm .php" >> /usr/local/etc/php-fpm.d/www.conf
              php-fpm

...

 

변경된 컨테이너를 적용합니다.

# docker compose stop php
# docker rm -v php
# docker compose up -d php

 

2) mysql 연동 및 테스트

 

php 컨테이너에서 docker-php-ext-install 명령을 이용해 필요한 라이브러리를 설치해줍니다. (mysqli.so 파일 생성)

# docker exec -it php /bin/bash

root@8e2d3bf1c94f:/var/www/html# docker-php-ext-install mysqli

 

호스트 서버에서 설정 파일을 열고 아래 행을 주석 해제 합니다.

# vi /home/sysdocu/php/conf/php.ini

extension=mysqli

 

변경 사항을 적용합니다.

# docker compose restart php

 

웹 소스를 수정하여 MySQL 연동이 잘 되는지 테스트 해봅니다.

아래 소스 코드를 이용하여 작성한 뒤 웹브라우저에서 접근하면 확인이 가능합니다.

 

# vi /home/sysdocu/httpd/html/index.html

MySQL Connect TEST<br>
<?
$conn = mysqli_connect("mysql", "sysdocu", "12345678", "sysdocudb"); # 여기에서 mysql 은 컨테이너 이름

if ($conn) {
    echo "MySQL 연결 성공";
} else {
    echo "MySQL 연결 실패";
}

$result = mysqli_query($conn, "SELECT VERSION() AS VERSION");
$data = mysqli_fetch_assoc($result);
echo "<br>Version : " . $data['VERSION'];
?>

 

3) 기타 라이브러리 활성화

 

주로 사용하는 curl, gd, mbstring, openssl 라이브러리를 활성해 보겠습니다.

(사실 gd 만 추가 설치, 나머지는 재설치 과정)

mysqli 설치하는 방법과 같이 컨테이너에 접근하여 라이브러리를 설치하면 되지만,

그냥 설치 명령을 내리면 컨테이너에 필요한 패키지가 없다며 에러가 출력되므로

사전에 필요한 패키지를 설치하고 라이브러리 설치를 진행합니다.

# docker exec -it php /bin/bash

 

제일 먼저 리포지토리를 정리해야 패키지 설치가 잘 되므로 업데이트를 해줍니다.

root@8e2d3bf1c94f:/var/www/html# apt -y update

 

(curl 라이브러리 설치)

root@8e2d3bf1c94f:/var/www/html# apt -y install libcurl4-openssl-dev

root@8e2d3bf1c94f:/var/www/html# docker-php-ext-install curl

 

(gd 라이브러리 설치)

root@8e2d3bf1c94f:/var/www/html# apt -y install zlib1g-dev libpng-dev

root@8e2d3bf1c94f:/var/www/html# docker-php-ext-install gd

gd 는 기본 허용 모듈에서 빠져 있기 때문에 사용을 위해 아래와 같이 추가 구성해줍니다.

root@8e2d3bf1c94f:/var/www/html# docker-php-ext-configure --with-gd

 

(mbstring 라이브러리 설치)

root@8e2d3bf1c94f:/var/www/html# apt -y install libonig-dev

root@8e2d3bf1c94f:/var/www/html# docker-php-ext-install mbstring

 

(openssl 라이브러리 설치)

root@8e2d3bf1c94f:/var/www/html# cd /usr/src/php/ext/openssl
root@233900ce6ef9:/usr/src/php/ext/openssl# cp config0.m4 config.m4
root@233900ce6ef9:/usr/src/php/ext/openssl# phpize
root@233900ce6ef9:/usr/src/php/ext/openssl# # apt -y install libssl-dev
root@233900ce6ef9:/usr/src/php/ext/openssl# docker-php-ext-install openssl

 

라이브러리 설치 완료 후 php 컨테이너를 재시작 하면 phpinfo 화면에서 설치한 모듈이 보여지게 됩니다.

# docker compose restart php

# docker exec php php -i |grep -i gd

 

반응형

댓글()