<aside> 👉🏻 필자는 Apple M1 Pro 사용 중이여, 해당 mac으로 아래 실습 내용을 정리하였습니다.
</aside>
배경 : 자신의 로컬 PC에서 쿠버네티스 공부를 위해서 환경 구성 시, Intel CPU 경우 VirtualBox + Vagrant 를 사용 시 가장 편리하게 실습이 가능합니다.
Apple Silicon M 시리즈 CPU 정보 확인
# 브랜드 정보
**sysctl -a |grep -i brand**
machdep.cpu.brand_string: Apple M1 Pro
# CPU 아키텍처 정보
**arch**
arm64
CPU 아키텍처 별 도커 컨테이너 실행 확인 - Link
https://hub.docker.com/_/ubuntu
# arm64v8 실행 성공!
**docker run --rm -it arm64v8/ubuntu arch**
aarch64
# arm64v8 실행 시도
**docker** run --rm -it **amd64**/ubuntu **arch**
*WARNING: The requested image's platform (linux/amd64) **does not match the detected host platform (linux/arm64/v8**) and no specific platform was requested*
# riscv64 실행 시도
**docker** run --rm -it **riscv64**/ubuntu **arch**
*WARNING: The requested image's platform (linux/amd64) **does not match the detected host platform (linux/arm64/v8**) and no specific platform was requested*
⇒ kind 경우 ARM 컨테이너 이미지 제공!
# 아래 kind 클러스터에서 노드(?) CPU 정보 확인
**docker exec -it kind-control-plane arch**
aarch64
소개 : ‘도커 IN 도커 docker in docker’로 쿠버네티스 클러스터 환경을 구성 - Link
그림 출처: https://kind.sigs.k8s.io/
설치
Docker Desktop 설치 - Link
kind 및 툴 설치
# Install Kind
**brew install kind**
kind --version
# Install kubectl
**brew install kubernetes-cli**
kubectl version --client=true
# Install Helm
**brew install helm**
helm version
kind 기본 사용 - 클러스터 배포 및 확인
# 클러스터 배포 전 확인
docker ps
# Create a cluster with kind
**kind create cluster**
# 클러스터 배포 확인
kind get clusters
kind get nodes
kubectl cluster-info
# 노드 정보 확인
kubectl get node -o wide
# 파드 정보 확인
kubectl get pod -A
kubectl get componentstatuses
# 컨트롤플레인 (컨테이너) 노드 1대가 실행
docker ps
docker images
# kube config 파일 확인
cat ~/.kube/config
# 노드에 Taints 정보 확인
**kubectl describe node | grep Taints**
Taints: <none>
# nginx 파드 배포 및 확인
kubectl run nginx --image=nginx
kubectl get pod -owide
# 삭제
**kind delete cluster**
# kube config 삭제 확인
cat ~/.kube/config
kind 상세 정보 확인 : Docker in Docker 확인
기본 정보 확인
# 클러스터 배포 전 확인
docker ps
# kind 는 별도 도커 네트워크 생성 후 사용 : 172.18.0.0/16
docker network ls
# Create a cluster with kind
**kind create cluster --name myk8s**
# 확인
kind get nodes --name **myk8s**
kubectl cluster-info
# 노드 정보 확인 : CRI 는 containerd 사용
kubectl get node -o wide
# 파드 정보 확인 : CNI 는 kindnet 사용
kubectl get pod -A
# 컨트롤플레인 컨테이너 1대가 실행 : 도커 컨테이너 이름은 **myk8s**-control-plane 임을 확인
docker ps
docker images
# kube config 파일 확인
cat ~/.kube/config
# local-path 라는 StorageClass 가 설치, local-path 는 노드의 로컬 저장소를 활용함
# 로컬 호스트의 path 를 지정할 필요 없이 local-path provisioner 이 볼륨을 관리
kubectl get sc
kubectl get deploy -n local-path-storage
파드 생성 및 확인
# 파드 생성
cat <<EOF | kubectl create -f -
apiVersion: v1
kind: **Pod**
metadata:
name: **netpod**
spec:
containers:
- name: netshoot-pod
image: **nicolaka/netshoot**
command: ["tail"]
args: ["-f", "/dev/null"]
terminationGracePeriodSeconds: 0
---
apiVersion: v1
kind: **Pod**
metadata:
name: **nginx**
spec:
containers:
- name: nginx-pod
image: **nginx:alpine**
terminationGracePeriodSeconds: 0
EOF
# 파드 확인
kubectl get pod -owide
# netpod 파드에서 nginx 웹 접속
kubectl exec -it netpod -- curl -s $(kubectl get pod nginx -o jsonpath={.status.podIP}) | grep -o "<title>.*</title>"
<title>Welcome to nginx!</title>
컨트롤플레인 컨테이너 정보 확인 : 아래 “Node” Container 은 ‘myk8s-control-plane’ 컨테이너 (그림에 빨간색) 입니다
# 도커 컨테이너 확인
docker ps
docker inspect **myk8s**-control-plane
...
"Path": "/usr/local/bin/entrypoint",
"**Args**": [
"**/sbin/init**"
],
...
# 컨트롤플레인 컨테이너 bash 접속 후 확인
docker exec -it **myk8s**-control-plane bash
-------------------------------------------
# CPU 정보 확인
**arch**
***aarch64***
# 기본 사용자 확인
**whoami**
***root***
# 네트워크 정보 확인
ip -br -c -4 addr
ip -c route
cat /etc/resolv.conf
# 프로세스 확인 : PID 1 은 /sbin/init
**ps -ef**
# 컨테이터 런타임 정보 확인
**systemctl status containerd**
# DinD 컨테이너 확인 : crictl 사용
crictl version
crictl info
crictl ps -o json | jq -r '.containers[] | {NAME: .metadata.name, POD: .labels["io.kubernetes.pod.name"]}'
**crictl ps**
*CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID POD
ff3d3a53905fd 9d6767b714bf1 12 minutes ago Running **nginx-pod** 0 20328fe63d512 nginx
bebe6b14d1ab3 eead9e442471d 13 minutes ago Running **netshoot-pod** 0 28cd918f0561a netpod
4bc2056cff78b 2437cf7621777 15 minutes ago Running **coredns** 0 0dd58c451b3d8 coredns-76f75df574-kj9pg
e6cd26bc67aa9 6c806bad1e899 15 minutes ago Running **local-path-provisioner** 0 0782f7f79949f local-path-provisioner-7577fdbbfb-8b2b9
0cd01fde90478 2437cf7621777 15 minutes ago Running **coredns** 0 bf54d53671d63 coredns-76f75df574-lsmdw
efe9bae31b499 4740c1948d3fc 15 minutes ago Running **kindnet-cni** 0 b73cc4c286e03 kindnet-dqw7r
9467b37fd627d b0f66293758c3 15 minutes ago Running **kube-proxy** 0 723f6784be90b kube-proxy-qh9vk
e69e359ebcdc8 79f8d13ae8b88 15 minutes ago Running **etcd** 0 baa0d331afd0d etcd-myk8s-control-plane
f50cef8ddd542 77288ad01f953 15 minutes ago Running **kube-apiserver** 0 f31087de549b6 kube-apiserver-myk8s-control-plane
945a25620e999 eb00b05fd5dbf 15 minutes ago Running **kube-controller-manager** 0 6a7cf01ca54e1 kube-controller-manager-myk8s-control-plane
5034555531d01 226bca0da8460 15 minutes ago Running **kube-scheduler** 0 8a32d8f342f6f kube-scheduler-myk8s-control-plane*
# 파드 이미지 확인
**crictl images**
*IMAGE TAG IMAGE ID SIZE
docker.io/kindest/kindnetd v20240202-8f1494ea 4740c1948d3fc 25.3MB
docker.io/kindest/local-path-helper v20230510-486859a6 d022557af8b63 2.92MB
docker.io/kindest/local-path-provisioner v20240202-8f1494ea 6c806bad1e899 17.3MB
docker.io/library/nginx alpine 9d6767b714bf1 20.2MB
docker.io/nicolaka/netshoot latest eead9e442471d 178MB
registry.k8s.io/coredns/coredns v1.11.1 2437cf7621777 16.5MB
registry.k8s.io/etcd 3.5.10-0 79f8d13ae8b88 65.2MB
registry.k8s.io/kube-apiserver-arm64 v1.29.2 77288ad01f953 83.3MB
registry.k8s.io/kube-apiserver v1.29.2 77288ad01f953 83.3MB
registry.k8s.io/kube-controller-manager-arm64 v1.29.2 eb00b05fd5dbf 77.7MB
registry.k8s.io/kube-controller-manager v1.29.2 eb00b05fd5dbf 77.7MB
registry.k8s.io/kube-proxy-arm64 v1.29.2 b0f66293758c3 86.6MB
registry.k8s.io/kube-proxy v1.29.2 b0f66293758c3 86.6MB
registry.k8s.io/kube-scheduler-arm64 v1.29.2 226bca0da8460 59.1MB
registry.k8s.io/kube-scheduler v1.29.2 226bca0da8460 59.1MB
registry.k8s.io/pause 3.7 e5a475a038057 268kB*
# kubectl 확인
**kubectl get node -v6**
cat /etc/kubernetes/admin.conf
exit
-------------------------------------------
# 도커 컨테이너 확인 : 다시 한번 자신의 호스트PC에서 도커 컨테이너 확인
docker ps
클러스터 삭제
# 클러스터 삭제
**kind delete cluster --name myk8s**
docker ps
Multi-Node Cluster (Control-plane, Nodes) & Mapping ports - 링크
# '컨트롤플레인, 워커 노드 1대' 클러스터 배포 : 파드에 접속하기 위한 포트 맵핑 설정
cat <<EOT> **kind-2node.yaml**
# two node (one workers) cluster config
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
networking:
apiServerAddress: "0.0.0.0"
nodes:
**- role: control-plane
- role: worker**
extraPortMappings:
- **containerPort: 31000
hostPort: 31000**
listenAddress: "0.0.0.0" # Optional, defaults to "0.0.0.0"
protocol: tcp # Optional, defaults to tcp
- **containerPort: 31001
hostPort: 31001**
EOT
CLUSTERNAME=myk8s
kind create cluster --config **kind-2node.yaml** --name $CLUSTERNAME
# 배포 확인
kind get clusters
kind get nodes --name $CLUSTERNAME
# 노드 확인
kubectl get nodes -o wide
# 노드에 Taints 정보 확인
**kubectl describe node myk8s-control-plane | grep Taints**
Taints: node-role.kubernetes.io/control-plane:NoSchedule
**kubectl describe node myk8s-worker | grep Taints**
Taints: <none>
# 컨테이너 확인 : 컨테이너 갯수, 컨테이너 이름 확인
# kind yaml 에 포트 맵핑 정보 처럼, 자신의 PC 호스트에 31000 포트 접속 시, 워커노드(실제로는 컨테이너)에 TCP 31000 포트로 연결
# 즉, 워커노드에 NodePort TCP 31000 설정 시 자신의 PC 호스트에서 접속 가능!
docker ps
**docker port $CLUSTERNAME-worker**
*31000/tcp -> 0.0.0.0:31000
31001/tcp -> 0.0.0.0:31001*
# 컨테이너 내부 정보 확인 : 필요 시 각각의 노드(?)들에 bash로 접속하여 사용 가능
docker exec -it **$CLUSTERNAME-control-plane** ip -br -c -4 addr
docker exec -it **$CLUSTERNAME-worker** ip -br -c -4 addr
# 디플로이먼트와 서비스 배포
cat <<EOF | kubectl create -f -
apiVersion: apps/v1
kind: **Deployment**
metadata:
name: **deploy-websrv**
spec:
replicas: 2
selector:
matchLabels:
app: deploy-websrv
template:
metadata:
labels:
app: deploy-websrv
spec:
terminationGracePeriodSeconds: 0
containers:
- name: deploy-websrv
image: nginx:alpine
ports:
- containerPort: 80
---
apiVersion: v1
kind: **Service**
metadata:
name: **deploy-websrv**
spec:
ports:
- name: svc-webport
port: 80
targetPort: 80
nodePort: **31000**
selector:
app: deploy-websrv
type: NodePort
EOF
# 확인
**docker ps**
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
117a1145a676 kindest/node:v1.29.2 "/usr/local/bin/entr…" 7 minutes ago Up 7 minutes **0.0.0.0:31000-31001->31000-31001/tcp** **myk8s-worker**
...
**kubectl get deploy,svc,ep deploy-websrv**
...
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/deploy-websrv NodePort 10.96.204.112 <none> 80:**31000**/TCP 55s
...
# 자신의 PC에 호스트 포트 31000 접속 시 쿠버네티스 서비스에 접속 확인
**curl -s localhost:31000 | grep -o "<title>.*</title>"**
<title>Welcome to nginx!</title>
# 디플로이먼트와 서비스 삭제
kubectl delete deploy,svc deploy-websrv
# 클러스터 삭제
**kind delete cluster --name $CLUSTERNAME**
별도 kubeconfig 지정 후 사용
# 방안1 : 환경변수 지정
**export KUBECONFIG=/Users/*<Username>*/Downloads/kind/config**
# 방안2 : 혹은 --kubeconfig ./config 지정 가능
# 클러스터 생성
**kind create cluster**
# kubeconfig 파일 확인
**ls -l /Users/*<Username>*/Downloads/kind/config**
-rw------- 1 ***<Username>*** staff 5608 4 24 09:05 /Users/***<Username>***/Downloads/kind/config
# 파드 정보 확인
**kubectl get pod -A**
# 클러스터 삭제
**kind delete cluster
unset KUBECONFIG**
외부 컨테이너 이미지를 kind 쿠버 클러스터에 주입 - Link
# 컨트롤플레인(노드=컨테이너)에 로컬 이미지 확인
docker exec -it **$CLUSTERNAME**-control-plane **crictl images**
# 외부 컨테이너 이미지를 kind 쿠버 클러스터에 주입
**kind load docker-image catalog-service:0.0.1-SNAPSHOT --name $CLUSTERNAME**
# 컨트롤플레인(노드=컨테이너)에 로컬 이미지 확인
docker exec -it **$CLUSTERNAME**-control-plane **crictl images**
*...
docker.io/library/catalog-service 0.0.1-SNAPSHOT 27e9825daf852 299MB
...*
# 디플로이먼트 배포 실행 : 로컬 이미지 사용 확인
**kubectl create deployment catalog-service --image=catalog-service:0.0.1-SNAPSHOT**
kubectl get deploy,pod
**kubectl** scale deployment catalog-service --replicas 2