본문 바로가기

K8S

쿠버네티스(Kubernetes) 실습 환경 구성 - 쿠버네티스/CNI 구성

728x90

■ 쿠버네티스 클러스터 구성

  • 쿠버네티스가 설치 된 호스트에 기본 게이트웨이가 2개 이상일 경우, 첫 번째 게이트웨이 정보를 사용 합니다.
  • 기본 경로가 없거나, 쿠버네티스 구성요소와 통신할 수 없을 경우 장애가 발생하게 됩니다.
  • Control-Plane IP 주소는 X.509 인증서에서 name 영역을 대체하게 됩니다. 그래서 IP 주소가 변경되게 된다면 영향을 받는 모든 구성요소를 재시작하고 인증서를 수동으로 변경해주어야 합니다.
  • 쿠버네티스 클러스터를 구성할 때 쿠버네티스 전용 HOST Network 를 구성할 것을 권장 합니다.
  • kubeadm을 이용한 쿠버네티스 클러스터 구성
sudo kubeadm init --pod-network-cidr=10.96.0.0/12 --apiserver-advertise-address=192.168.56.10
#--pod-network-cidr: pod 간 통신할 IP 주소를 지정 합니다. 
#--apiserver-advertise-address: Control-plane의 api-server가 사용할 IP 주소 입니다. 지정하지 않으면 default network interface 주소를 사용 합니다
#--service-cidr: 클러스터 내에서 애플리케이션 간 통신을 위해 사용되며, 고유한 IP 주소를 가지게 되며 기본값으로 10.96.0.0/12을 가집니다.
#pod-network-cidr과 --service-cidr 주소를 겹치지 않게 설정. 겹칠 경우 쿠버네티스가 중복되지 않게 배치함

 

  • kubeadm init 명령어 수행 결과
sudo kubeadm init --pod-network-cidr=10.96.0.0/12 --apiserver-advertise-address=192.168.56.10
[sudo] kidong 암호:
I0707 13:02:53.499227    2788 version.go:256] remote version is much newer: v1.30.2; falling back to: stable-1.28
[init] Using Kubernetes version: v1.28.11
[preflight] Running pre-flight checks
[preflight] Pulling images required for setting up a Kubernetes cluster
[preflight] This might take a minute or two, depending on the speed of your internet connection
[preflight] You can also perform this action in beforehand using 'kubeadm config images pull'
W0707 13:03:17.438549    2788 checks.go:835] detected that the sandbox image "registry.k8s.io/pause:3.8" of the container runtime is inconsistent with that used by kubeadm. It is recommended that using "registry.k8s.io/pause:3.9" as the CRI sandbox image.
[certs] Using certificateDir folder "/etc/kubernetes/pki"
[certs] Generating "ca" certificate and key
[certs] Generating "apiserver" certificate and key
[certs] apiserver serving cert is signed for DNS names [k8smaster kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] and IPs [10.96.0.1 192.168.56.10]
[certs] Generating "apiserver-kubelet-client" certificate and key
[certs] Generating "front-proxy-ca" certificate and key
[certs] Generating "front-proxy-client" certificate and key
[certs] Generating "etcd/ca" certificate and key
[certs] Generating "etcd/server" certificate and key
[certs] etcd/server serving cert is signed for DNS names [k8smaster localhost] and IPs [192.168.56.10 127.0.0.1 ::1]
[certs] Generating "etcd/peer" certificate and key
[certs] etcd/peer serving cert is signed for DNS names [k8smaster localhost] and IPs [192.168.56.10 127.0.0.1 ::1]
[certs] Generating "etcd/healthcheck-client" certificate and key
[certs] Generating "apiserver-etcd-client" certificate and key
[certs] Generating "sa" key and public key
[kubeconfig] Using kubeconfig folder "/etc/kubernetes"
[kubeconfig] Writing "admin.conf" kubeconfig file
[kubeconfig] Writing "kubelet.conf" kubeconfig file
[kubeconfig] Writing "controller-manager.conf" kubeconfig file
[kubeconfig] Writing "scheduler.conf" kubeconfig file
[etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests"
[control-plane] Using manifest folder "/etc/kubernetes/manifests"
[control-plane] Creating static Pod manifest for "kube-apiserver"
[control-plane] Creating static Pod manifest for "kube-controller-manager"
[control-plane] Creating static Pod manifest for "kube-scheduler"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Starting the kubelet
[wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory "/etc/kubernetes/manifests". This can take up to 4m0s
[apiclient] All control plane components are healthy after 6.517863 seconds
[upload-config] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
[kubelet] Creating a ConfigMap "kubelet-config" in namespace kube-system with the configuration for the kubelets in the cluster
[upload-certs] Skipping phase. Please see --upload-certs
[mark-control-plane] Marking the node k8smaster as control-plane by adding the labels: [node-role.kubernetes.io/control-plane node.kubernetes.io/exclude-from-external-load-balancers]
[mark-control-plane] Marking the node k8smaster as control-plane by adding the taints [node-role.kubernetes.io/control-plane:NoSchedule]
[bootstrap-token] Using token: pa4b6j.xsmaoye25jvhql3t
[bootstrap-token] Configuring bootstrap tokens, cluster-info ConfigMap, RBAC Roles
[bootstrap-token] Configured RBAC rules to allow Node Bootstrap tokens to get nodes
[bootstrap-token] Configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials
[bootstrap-token] Configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token
[bootstrap-token] Configured RBAC rules to allow certificate rotation for all node client certificates in the cluster
[bootstrap-token] Creating the "cluster-info" ConfigMap in the "kube-public" namespace
[kubelet-finalize] Updating "/etc/kubernetes/kubelet.conf" to point to a rotatable kubelet client certificate and key
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy

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

#ROOT 사용자를 위한 코드, 일반 계정을 사용할 경우 아래는 생략
Alternatively, if you are the root user, you can run:

  export KUBECONFIG=/etc/kubernetes/admin.conf

#네트워크 구성 및 네트워크 정책을 위한 third party (add-on)
#현재 구성에서는 calico 사용
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 192.168.56.10:6443 --token pa4b6j.xsmaoye25jvhql3t \
	--discovery-token-ca-cert-hash sha256:d4f955570781216fdd6aa2cc53f82787e367cf8bb6e1cb16d08c879783998e5c

 

  • 클러스터 시작을 위한 설정
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

#ROOT 게정 사용자일 경우 
Alternatively, if you are the root user, you can run:

  export KUBECONFIG=/etc/kubernetes/admin.conf

 

  • kubelet 자동완성 기능 설치
sudo apt-get install -y bash-completion
source <(kubectl completion bash)
echo "source <(kubectl completion bash)" >> ~/.bashrc
source .bashrc

 

  • 쿠버네티스 활성화 포트 및 노드 확인
    - 쿠버네티스의 노드는 현재 네트워킹 서비스가 활성화 되어 있지 않아, 마스터 노드만 확인
sudo netstat -ntlp | grep LISTEN
tcp        0      0 127.0.0.1:6010          0.0.0.0:*               LISTEN      2147/sshd: kidong@p
tcp        0      0 127.0.0.1:40867         0.0.0.0:*               LISTEN      1144/containerd
tcp        0      0 192.168.56.10:2380      0.0.0.0:*               LISTEN      3450/etcd
tcp        0      0 192.168.56.10:2379      0.0.0.0:*               LISTEN      3450/etcd
tcp        0      0 127.0.0.1:631           0.0.0.0:*               LISTEN      1136/cupsd
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      401/systemd-resolve
tcp        0      0 127.0.0.54:53           0.0.0.0:*               LISTEN      401/systemd-resolve
tcp        0      0 127.0.0.1:10259         0.0.0.0:*               LISTEN      3428/kube-scheduler
tcp        0      0 127.0.0.1:10257         0.0.0.0:*               LISTEN      3412/kube-controlle
tcp        0      0 127.0.0.1:10249         0.0.0.0:*               LISTEN      3703/kube-proxy
tcp        0      0 127.0.0.1:10248         0.0.0.0:*               LISTEN      3617/kubelet
tcp        0      0 127.0.0.1:2379          0.0.0.0:*               LISTEN      3450/etcd
tcp        0      0 127.0.0.1:2381          0.0.0.0:*               LISTEN      3450/etcd
tcp6       0      0 ::1:631                 :::*                    LISTEN      1136/cupsd
tcp6       0      0 :::6443                 :::*                    LISTEN      3440/kube-apiserver
tcp6       0      0 :::22                   :::*                    LISTEN      1/init
tcp6       0      0 :::10256                :::*                    LISTEN      3703/kube-proxy
tcp6       0      0 :::10250                :::*                    LISTEN      3617/kubelet
tcp6       0      0 ::1:6010                :::*                    LISTEN      2147/sshd: kidong@p

kubectl get node
NAME        STATUS     ROLES           AGE    VERSION
k8smaster   NotReady   control-plane   134m   v1.28.11

kubectl get po -A
NAMESPACE     NAME                                READY   STATUS    RESTARTS   AGE
kube-system   coredns-5dd5756b68-sll5x            0/1     Pending   0          135m
kube-system   coredns-5dd5756b68-sxwm6            0/1     Pending   0          135m
kube-system   etcd-k8smaster                      1/1     Running   0          135m
kube-system   kube-apiserver-k8smaster            1/1     Running   0          135m
kube-system   kube-controller-manager-k8smaster   1/1     Running   0          135m
kube-system   kube-proxy-zq8d7                    1/1     Running   0          135m
kube-system   kube-scheduler-k8smaster            1/1     Running   0          135m

 

  • JOIN KEY를 이용한 클러스터 조인
    - JOIN KEY는 kubeadm init 명령어 결과의 하단 부분에 노출 됨
    - sudo를 붙여 Worker Node에 입력
    - Node join 이후 클러스터 정보 조회 
sudo kubeadm join 192.168.56.10:6443 --token pa4b6j.xsmaoye25jvhql3t \
        --discovery-token-ca-cert-hash sha256:d4f955570781216fdd6aa2cc53f82787e367cf8bb6e1cb16d08c879783998e5c

#쿠버네티스 정보 조회 
kubectl get node
NAME        STATUS     ROLES           AGE    VERSION
k8smaster   NotReady   control-plane   138m   v1.28.11
k8snode1    NotReady   <none>          115s   v1.28.11
k8snode2    NotReady   <none>          100s   v1.28.11

kubectl get po -A #또는 kubectl get pod --all-namespaces
#coredns 외 모든 항목이 running 상태 확인
#coredns 는 네트워킹 환경 구성이 완료 되어야 running 상태 변경
NAMESPACE     NAME                                READY   STATUS    RESTARTS   AGE
kube-system   coredns-5dd5756b68-sll5x            0/1     Pending   0          141m
kube-system   coredns-5dd5756b68-sxwm6            0/1     Pending   0          141m
kube-system   etcd-k8smaster                      1/1     Running   0          141m
kube-system   kube-apiserver-k8smaster            1/1     Running   0          141m
kube-system   kube-controller-manager-k8smaster   1/1     Running   0          141m
kube-system   kube-proxy-fknmr                    1/1     Running   0          4m3s
kube-system   kube-proxy-vk8hz                    1/1     Running   0          4m18s
kube-system   kube-proxy-zq8d7                    1/1     Running   0          141m
kube-system   kube-scheduler-k8smaster            1/1     Running   0          141m

■ 쿠버네티스 CNI (Container Network Interface) 소개

  • CNI는 컨테이너 간 네트워킹을 제어할 수 있는 플러그인을 만들기 위한 표준
  • 다양한 형태의 컨테이너 런타임과 오케스트레이터 사이의 네트워크 계층을 구현하는 방식이 다양하게 분리되어 각자만의 방식으로 발전하게 되는 것을 방지하고 공통의 인터페이스를 제공하는 역할 수행
  • 쿠버네티스는 Pod간 통신을 위해 CNI 사용. 쿠버네티스는 기본적으로 "kubenet" 이라는 CNI를 제공하나 기능이 제한적이라 third-party 플러그인 사용. 

 

■ 쿠버네티스 CNI (Container Network Interface) 필요성

  • 노드에 존재하는 컨테이너 네트워크의 IP 대역이 동일하여 Pod들이 같은 IP를 할당 받을 가능성이 존재함
  • Pod에 할당된 IP를 서로 다른 Pod에서 인식하기 위함 (ex: eBPG VXLAN)
  • 중복되지 않는 IP 할당 및 Worker Node에서 실행되는 Pod는 유효한 서브넷의 IP를 할당 받기 위해 CNI가 필요함

 

■ 쿠버네티스 CNI (Container Network Interface) 구성

curl -O https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/calico.yaml
kubectl apply -f calico.yaml

#CNI 설치 이후 calico 가 init 상태, 네트워킹 구성이 완료 되면 모든 구성이 running 상태 변경
kubectl get po -A
kube-system       calico-kube-controllers-658d97c59c-rfwjr   1/1     Running   0          2m29s
kube-system       calico-node-4qcv4                          1/1     Running   0          2m29s
kube-system       calico-node-hshgl                          1/1     Running   0          2m29s
kube-system       calico-node-k4j4r                          1/1     Running   0          2m29s
kube-system       coredns-5dd5756b68-sll5x                   1/1     Running   0          173m
kube-system       coredns-5dd5756b68-sxwm6                   1/1     Running   0          173m
kube-system       etcd-k8smaster                             1/1     Running   0          173m
kube-system       kube-apiserver-k8smaster                   1/1     Running   0          173m
kube-system       kube-controller-manager-k8smaster          1/1     Running   0          173m
kube-system       kube-proxy-fknmr                           1/1     Running   0          36m
kube-system       kube-proxy-vk8hz                           1/1     Running   0          36m
kube-system       kube-proxy-zq8d7                           1/1     Running   0          173m
kube-system       kube-scheduler-k8smaster                   1/1     Running   0          173m
tigera-operator   tigera-operator-8547bd6cc6-9gn2x           1/1     Running   0          11m

#네트워킹 구성 완료 후 노드 정보 조회 시 NotReady에서 Ready로 변경 확인
kubectl get node
NAME        STATUS   ROLES           AGE    VERSION
k8smaster   Ready    control-plane   177m   v1.28.11
k8snode1    Ready    <none>          40m    v1.28.11
k8snode2    Ready    <none>          40m    v1.28.11

#클러스터 정보 확인
kubectl cluster-info

#클러스터 초기 설정값 확인
kubeadm config print init-defaults

 

 

■ 쿠버네티스 CNI (Container Network Interface) Calico 기능

kubectl exec -n kube-system calicoctl -- calicoctl -h
Usage:
  calicoctl [options] <command> [<args>...]

    create       Create a resource by file, directory or stdin.
    replace      Replace a resource by file, directory or stdin.
    apply        Apply a resource by file, directory or stdin.  This creates a resource
                 if it does not exist, and replaces a resource if it does exists.
    patch        Patch a pre-exisiting resource in place.
    delete       Delete a resource identified by file, directory, stdin or resource type and
                 name.
    get          Get a resource identified by file, directory, stdin or resource type and
                 name.
    label        Add or update labels of resources.
    convert      Convert config files between different API versions.
    ipam         IP address management.
    node         Calico node management.
    version      Display the version of this binary.
    export       Export the Calico datastore objects for migration
    import       Import the Calico datastore objects for migration
    datastore    Calico datastore management.

Options:
  -h --help               Show this screen.
  -l --log-level=<level>  Set the log level (one of panic, fatal, error,
                          warn, info, debug) [default: panic]
  • 네트워크 IP 주소 할당/회수 및 관리 
#calico가 관리하는 IP Pool 전체 
kubectl exec -n kube-system calicoctl -- calicoctl ipam show
+----------+--------------+------------+------------+-------------------+
| GROUPING |     CIDR     | IPS TOTAL  | IPS IN USE |     IPS FREE      |
+----------+--------------+------------+------------+-------------------+
| IP Pool  | 10.96.0.0/12 | 1.0486e+06 | 7 (0%)     | 1.0486e+06 (100%) |
+----------+--------------+------------+------------+-------------------+

#calico가 관리하는 IP Pool CIDR 단위
#해당 정보를 참조하여 워커 노드에서 사용하는 IP 확인 
kubectl exec -n kube-system calicoctl -- calicoctl ipam show --show-block
+----------+-------------------+------------+------------+-------------------+
| GROUPING |       CIDR        | IPS TOTAL  | IPS IN USE |     IPS FREE      |
+----------+-------------------+------------+------------+-------------------+
| IP Pool  | 10.96.0.0/12      | 1.0486e+06 | 7 (0%)     | 1.0486e+06 (100%) |
| Block    | 10.101.174.128/26 |         64 | 1 (2%)     | 63 (98%)          |
| Block    | 10.102.249.0/26   |         64 | 1 (2%)     | 63 (98%)          |
| Block    | 10.108.185.192/26 |         64 | 4 (6%)     | 60 (94%)          |
| Block    | 10.98.16.128/26   |         64 | 1 (2%)     | 63 (98%)          |
+----------+-------------------+------------+------------+-------------------+

 

 

  • BIRD를 통해 각 Node의 라우팅 정보 공유 
    • calico는 가상 라우터(vRouter)를 생성하고, 가상 라우터는 BGP를 이용하여 Node의 라우팅 정보 공유
    • 컨테이너가 특정 Pod에 생성되면 IP를 할당 받게 됨. 
    • IP는 Pod가 위치하고 있는 물리적인 서버에서 "cali"로 시작하는 가상의 인터페이스가 생성되며 바인딩
    • cali로 시작하는 가상의 인터페이스는 가상의 라우터와 연결됨
    • 물리서버 (호스트)의 물리 인터페이스는 tunnel 이라는 가상 인터페이스와 연결되어 있음
    • tunnel 가상 인터페이스는 가상 라우터와 연결되어 있음.
    • 아래 이미지 구조로 네트워크가 구성되고 외부와 통신을 수행 함. 


kubeadm: https://v1-28.docs.kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/

kubeadm init 명령어: https://v1-28.docs.kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm-init/

쿠버네티스 네트워크 모델: https://github.com/kubernetes/design-proposals-archive/blob/main/network/networking.md

728x90