쿠버네티스가 v1.20 이후 컨테이너 런타임으로서 도커를 사용을 depricated🥊 한다고 한다
그렇기 때문에 컨테이너 런타임을 docker
에서 쿠버네티스가 계속 지원하는 다른 종류로 변경할 필요가 있다.
참고 : https://kubernetes.io/ko/blog/2020/12/02/dont-panic-kubernetes-and-docker/
그림 출처 : https://www.redhat.com/ko/topics/containers/kubernetes-architecture
기존 도커 같은 경우 다음과 같이 도커심
이라는 구성요소를 사용해 kubernetes와 연결을 지원하였다. 이유는 도커가 컨테이너 런타임 인터페이스인 CRI를 준수하지 않았기 때문이다. 쿠버네티스 v1.23부터는 이 도커심의 지원이 제거된다. 그렇다면 v1.20 부터 Docker로 빌드한 이미지를 사용 불가능할까?
그것은 아니다. docker build 한 이미지는 kubernetes 클러스터에서 계속 실행할 수 있다. 쿠버네티스가 지원하는 다른 컨테이너 런타임인 containerd 와 CRI-O 가 도커 이미지를 가져와 실행하는 법을 알고 있기 때문이다.
그럼 쿠버네티스가 지원하는 다른 컨테이너 런타임 종류를 알아보자.
지금 부터 소개하는 컨테이너 런타임은 쿠버네티스에서 만든 컨테이너 런타임 인터페이스와 호환되는 컨테이너 런타임이다. 따라서 도커심같은 중간 매체가 필요없다.
https://kubernetes.io/ko/docs/setup/production-environment/container-runtimes/#containerd
https://github.com/cri-o/cri-o
장점
단점 :
환경
kubernetes 1.22
또한 이런 컨테이너 런타임 컨테이너는 이미지를 빌드할 수 있는 기능을 제공하는 툴이랑 같이 사용할 수 있는데 종류는 아래와 같이 있다.
https://github.com/GoogleContainerTools/kaniko
도커 파일 없이 다른 스크립트 언어를 사용하는 것이 목표. 도커 파일도 사용가능
OCI 이미지 생성
buildah, Podman, skopeo는 도커기능을 역할별로 나눠서 제공해준다.
kaniko는 buildah의 역할이랑 같다. 다만 kaniko는 하나로 충분하지만 buildah는 podman이랑 같이 사용해야 한다.
사전 준비
kubeadm reset
sudo apt-get purge kubeadm kubectl kubelet kubernetes-cni kube*
sudo apt-get autoremove
sudo rm -rf ~/.kube
sudo apt-get purge docker-ce=18.06.2~ce~3-0~ubuntu -y
sudo apt-get remove docker docker-engine docker.io containerd runc
sudo apt-get autoremove
docker version
kubectl version
kubeadm version
kubelet --version
cat <<EOF | sudo tee /etc/modules-load.d/containerd.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
# 필요한 sysctl 파라미터를 설정하면 재부팅 후에도 유지된다.
cat <<EOF | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF
# 재부팅하지 않고 sysctl 파라미터 적용
sudo sysctl --system
https://docs.docker.com/engine/install/ubuntu/
sudo apt-get update
sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg \
lsb-release
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo \
"deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install containerd.io
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml
sudo systemctl restart containerd
vi /etc/containerd/config.toml
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
SystemdCgroup = true
sudo systemctl restart containerd
sudo apt-get update
sudo apt-get upgrade
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
cat <<EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list
deb https://apt.kubernetes.io/ kubernetes-xenial main
EOF
sudo apt-get update
sudo apt-get upgrade
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
cat <<EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list
deb https://apt.kubernetes.io/ kubernetes-xenial main
EOF
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
kubeadm version
kubelet --version
kubectl version # 클라이언트만 정상인지 확인
# 소캣 지정 필수
sudo kubeadm init --pod-network-cidr=10.244.0.0/16 --apiserver-advertise-address=192.168.60.4 --cri-socket /run/containerd/containerd.sock
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
kubeadm join 192.168.60.4:6443 --token scfdsafw.g1fsa.dfmhnm6 \
--discovery-token-ca-cert-hash sha256:85efdaskfja;sdlkf58efb5 --cri-socket /run/containerd/containerd.sock
vi kube-flannel.yml
kubectl apply -f kube-flannel.yml
이렇게 작업을 완료하고
다음과 같이 kubectl get node -o wide를 쳤을때 컨테이너 런타임이 containerd 가 뜨면 된다.
root@master:~# kubectl get node -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
master Ready control-plane,master 29h v1.22.3 192.168.60.4 <none> Ubuntu 18.04.6 LTS 5.4.0-89-generic containerd://1.4.11
node01 Ready <none> 29h v1.22.3 192.168.60.5 <none> Ubuntu 18.04.6 LTS 5.4.0-89-generic containerd://1.4.11
sudo apt-get update
sudo apt-get -y install buildah
간단한 스프링 부트 어플리케이션 올려보기
예전에 간단하게 만든 어플리케이션을 수정하여 생성
https://github.com/bo-yoon/efk_sample.git
Dockerfile
FROM openjdk:8-jdk-alpine
ARG JAR_FILE=build/libs/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]
buildah bud -t yoonkwon23/bps-app:latest .
buildah bud -t yoonkwon23/bps-app:latest .
STEP 1: FROM openjdk:8-jdk-alpine
STEP 2: ARG JAR_FILE=*.jar
STEP 3: COPY ${JAR_FILE} app.jar
STEP 4: ENTRYPOINT ["java", "-jar", "/app.jar"]
STEP 5: COMMIT yoonkwon23/bps-app:latest
Getting image source signatures
Copying blob f1b5933fe4b5 skipped: already exists
Copying blob 9b9b7f3d56a0 skipped: already exists
Copying blob ceaf9e1ebef5 skipped: already exists
Copying blob a760e1904a6e done
Copying config e587cd1ca6 done
Writing manifest to image destination
Storing signatures
e587cd1ca6c4e97b25cce50709dc8c44d855201f4e783461327829a4850d6f22
add-apt-repository -y ppa:projectatomic/ppa
sudo apt-get -y install podman
podman info
파드맨 인포를 보면 oci로 containerd가 설정되어 있는 것을 확인할 수 잇다.
echo -e "[registries.search]\nregistries = ['docker.io']" | sudo tee /etc/containers/registries.conf
podman run hello-world
podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/library/hello-world latest feb5d9fea6a5 6 days ago 17.4 kB
podman ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
208883ad3ee2 docker.io/library/hello-world:latest /hello About a minute ago Exited (0) About a minute ago awesome_tharp
podman login docker.io
skopeo 설치
sudo apt-get -y install skopeo
root@master:~# buildah images
REPOSITORY TAG IMAGE ID CREATED SIZE
localhost/yoonkwon23/bps-app latest 2457476c89a6 10 minutes ago 133 MB
root@master:~# python3 --version
Python 3.6.9
# cli 설치
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
aws --version
aws configure
AWS Access Key ID [None]:
AWS Secret Access Key [None]:
Default region name [None]: ap-northeast-2
Default output format [None]: json
aws ecr get-login-password --region ap-northeast-2 | podman login --username AWS --password-stdin {ecr 주소}
Login Succeeded!
aws ecr get-login-password --region ap-northeast-2 | buildah login --username AWS --password-stdin {ecr 주소}
Login Succeeded!
buildah {이미지 id} tag {이미지번호} {ecr 주소}:latest
buildah push {ecr 주소}:latest
ecr 을 보니 정상적으로 push한 것을 확인할 수 있다.
이제 쿠버네티스를 사용할 준비가 다 되었다.
파드를 올려보자!
podman tag {ecr 주소}:latest {ecr 주소}:3
podman push {ecr 주소}:3
아까 buildah 를 통해 만든 이미지가 있었는데 그 이미지를 podman으로 변환 후, ecr로 push 한다.
그리고 이 이미지를 베이스로 컨테이너를 실행한다.
podman run -id --name sample-pod2 -p 8090:8090 {ecr 주소}:3
이렇게 작업하면 podman ps 하면 컨테이너가 떠있는 것을 확인할 수 있는데
podman generate kube {컨테이너 id}
라고 치면 pod 타입의 yaml 파일 형식이 생겨날 것이다.
root@master:~# cat podman2.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
app: sample-pod2
name: sample-pod2
spec:
containers:
- env:
- name: PATH
value: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/lib/jvm/java-1.8-openjdk/jre/bin:/usr/lib/jvm/java-1.8-openjdk/bin
- name: TERM
value: xterm
- name: HOSTNAME
- name: container
value: podman
- name: LANG
value: C.UTF-8
- name: JAVA_HOME
value: /usr/lib/jvm/java-1.8-openjdk
- name: JAVA_VERSION
value: 8u212
- name: JAVA_ALPINE_VERSION
value: 8.212.04-r0
image: {ecr 주소}:{버전정보}
name: sample-pod2
ports:
- containerPort: 8090
hostPort: 8090
protocol: TCP
resources: {}
securityContext:
allowPrivilegeEscalation: true
capabilities: {}
privileged: false
readOnlyRootFilesystem: false
stdin: true
workingDir: /
status: {}
이것을 복사해서 podman2.yaml 이라는 파일을 만들어주었다. (첫번째는 실패했다...)
그리고 buildah images, podman images로 관련된 이미지를 다 삭제해준다. 이미지가 정상적으로 pull 되는지 확인하기 위해서이다.
이제 kubectl apply -f podman2.yaml 를 해본다
root@master:~/efk_sample# kubectl get pods
NAME READY STATUS RESTARTS AGE
sample-pod2 1/1 Running 0 27m
정상적으로 뜨는 것을 확인할 수 있다.
containerd
와 Kaniko
조합을, 아예 도커를 사용하지 않고 싶을 경우 CRI_O
와 buildah, Podman, skopeo
조합을 사용하는 것이 좋을 것 같다.