이론
Deployment
배포를 위한 오브젝트
Namespace
격리된 환경을 제공하는 오브젝트
Service
오브젝트들을 외부에 "서비스"하기 위한 오브젝트 = public
nodePort: 실제 서버외부에 노출되는 노드들의 포트이다. 30000~32765 까지의 포트가 사용 가능하다.
port: (서비스) 포트를 말한다. 서비스는 작은 로드밸런서라고 생각하면 좋다. IP와 port가 존재한다.
targetPort: pod의 포트이다.
실습
# <명령어 자동완성>
$ apt-get install bash-completion
$ echo 'source <(kubectl completion bash)' >>~/.bashrc
$ echo 'source <(kubeadm completion bash)' >>~/.bashrc
$ kubectl completion bash >/etc/bash_completion.d/kubectl
# kubectl 대신 k만 쳐도 되게끔 kubectl을 k로 간소화
$ ln -s /usr/bin/kubectl /usr/local/bin/k
Deployment
Pod
다음과 같이 pod를 띄워볼 수 있다.
$ vi test.yml
apiVersion: v1
kind: Pod
metadata:
name: http-t1
labels:
app: nginx
spec:
containers:
- name: nginx-container
image: http:latest
ports:
- containerPort: 80
$ kubectl apply -f test.yml
replicaset
replicaset은 pod를 몇 개 띄울지에 대한 것이다. 즉, pod를 복제하는 것에 대한 것이다.
replicaset을 통해 항상성(고가용성)을 확보할 수 있고, 버전관리에 반드시 필요하다.
"selector"를 통해 복제할 pod의 라벨을 선택한다.
$ vi nginx-rep.yml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: myrs
spec:
replicas: 3
selector:
matchLabels:
dev: my-label
template:
metadata:
name: mypod
labels:
dev: my-label
spec:
containers:
- name: mycon
image: nginx:latest
ports:
- containerPort: 80
$ kubectl apply -f nginx-rep.yml
# 정보확인.
# --watch : 실시간 모니터링
배포
1) “hello k8s”라는 index.html 파일을 httpd:latest 컨테이너를 베이스로 하여 k8s 로컬 클러스터에 배포하고 싶다.
- 인덱스 파일 생성 및 Dockerfile 작성
- 도커 이미지 빌드
- 매니페스트 파일 작성 => apply
$ echo "hello k8s" > index.html
$ vi Dockerfile
FROM httpd:latest
ADD ./index.html /usr/local/apache2/htdocs/index.html
# 도커 설치
$ curl -fsSL https://get.docker.com -o get-docker.sh
$ sudo sh get-docker.sh
# 빌드
$ docker build -t dahyeonn/myhttpd:1.0 .
# 로그인
$ docker login
# 도커 허브 push
$ docker push dahyeonn/myttpd:1.0
$ vi pod.yml
apiVersion: v1
kind: Pod
metadata:
name: myhttp
labels:
app: myhttp
spec:
containers:
- name: myhttp-con
image: dahyeonn/myhttpd:1.0
ports:
- containerPort: 80
$ kubectl apply -f pod.yml
2) replicaset을 3개로 하여 매니페스트 파일을 작성하고, 이미지는 도커 허브에 업로드 해서 구성해본다.
$ vi rep.yml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: mytthp-rep
spec:
replicas: 3
selector:
matchLabels:
app: my-http
template:
metadata:
name: mypod
labels:
app: my-http
spec:
containers:
- name: mycon
image: dahyeonn/myhttpd:latest
ports:
- containerPort: 80
$ kubectl apply -f rep.ym
3) 동일한 이미지를 사설저장소에 push하고 로컬 클러스터에 배포해본다.
# 사설 저장소 ip 예시: 125.178.222.208:5000
# 우리 클러스터의 CRI인 containerd의 설정 파일
$ vi /etc/containered/config.toml
# docker에서 /etc/docker/daemon.json 파일에서 사설저장소를 insecure 처리했던것처럼,
# containerd도 비슷한 설정을 해줘야 한다.
$ vi ip-rep.yml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: ip-rep
spec:
replicas: 3
selector:
matchLabels:
app: ip-http
template:
metadata:
labels:
app: ip-http
spec:
containers:
- name: myip
image: 125.178.222.208:5000/ipnginx:latest
ports:
- containerPort: 80
$ kubectl apply -f ip-rep.yml
$ kubectl get pod -o wide
# 이렇게 진행하면, 이미지를 못받아온다. (ImagePullBackOff)
# pod 이름으로 검색
$ kubectl describe pod ip-rep-czqf8
# 자세한 에러 확인
# containerd server gave HTTP response to HTTPS client
# 구글링을 해서 에러를 해결한다.
$ vi /etc/containerd/config.toml
# 아래의 내용을 추가한다.
# 3개의 노드에 전부 아래의 내용을 추가한다.
# 왜냐하면 실질적으로 image을 pulling 해와서 pod를 띄우는건 worker노드들이기 때문이다.
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."125.178.222.208:5000"]
endpoint = ["http://125.178.222.208:5000"]
[plugins."io.containerd.grpc.v1.cri".registry.configs."125.178.222.208:5000".tls]
insecure_skip_verify = true
# 해당 주소를 갖는(125.178.222.208:5000 의 사설저장소를 tls 인증서 없이(=https를 안하겠다) http로 사용하겠다.
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
http-t1 1/1 Running 0 19h
ip-rep-8gz5q 1/1 Running 0 18s
ip-rep-s6nqk 1/1 Running 0 18s
ip-rep-v8k5q 1/1 Running 0 18s
# 결론적으로 아래 명령어만 각 노드에 복붙하면 된다.
# 위에서 toml 파일 수정했으면 지우고 하거나 하지 않으면 된다.
export REG_ENDPOINT=125.178.222.208:5000
cat << EOF >> /etc/containerd/config.toml
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."${REG_ENDPOINT}"]
endpoint = ["http://${REG_ENDPOINT}"]
[plugins."io.containerd.grpc.v1.cri".registry.configs."${REG_ENDPOINT}".tls]
insecure_skip_verify = true
EOF
systemctl restart containerd
# 모든 파드를 삭제한다. 위험하지만, 실습으로 해본다.
$ kubectl delete pod --all --all-namespaces
4) deployment를 이용한 실습
$ vi ip-dep.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx-dep
spec:
replicas: 3
selector:
matchLabels:
app: my-nginx
template:
metadata:
name: my-nginx-pod
labels:
app: my-nginx
spec:
containers:
- name: nginx
image: 125.178.222.208:5000/ipnginx:latest
ports:
- containerPort: 80
Namespace
개념
# namespace 생성
$ vi myns.yml
apiVersion: v1
kind: Namespace
metadata:
name: myns
$ kubectl apply -f myns.yml
$ kubectl get ns
# 매니페스트 파일 상에서 ns 지정
$ vi nginx-pod.yml
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
namespace: myns
labels:
app: nginx
spec:
containers:
- name: nginx-container
image: nginx:test
ports:
- containerPort: 80
...
# 삭제
$ kubectl delete ns myns
namespace "myns" deleted
# namespace를 삭제하면 그 안에 있는 오브젝트들도 날라간다.
$ kubectl get pod --all-namespces | grep myns
배포
1) 하나의 매니페스트 파일(lunch-dep.yml)을 통해 lunch라는 namespace에 httpd:latest를 이미지로 하는 deployment를 만든다. 이때, deployment의 replicaset은 3개이다. kubectl apply -f lunch-dep.yml 명령어만 사용한다.
$ vi lunch-dep.yml
apiVersion: v1
kind: Namespace
metadata:
name: lunch
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: lunch-dep
namespace: lunch
spec:
replicas: 3
selector:
matchLabels:
app: food
template:
metadata:
labels:
app: food
spec:
containers:
- name: httpd-con
image: httpd:latest
ports:
- containerPort: 80
# 적용
$ kubectl apply -f lunch-dep.yml
# namespace의 pod 확인
$ kubectl get pod -n lunch
2) httpd:latest라는 이미지를 Pod로 하는 Deployment를 만들고 싶다. 레플리카는 3개로 하고 Pod의 라벨은 app: httpd로 해서 생성한다. 이때, web: httpd로 하면 안되고 app: httpd로 한다.
$ vi web-dep.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-httpd-dep
spec:
replicas: 3
selector:
matchLabels:
app: httpd
template:
metadata:
name: my-httpd-pod
labels:
app: httpd
spec:
containers:
- name: httpd-container
image: httpd:latest
ports:
- containerPort: 80
Service
개념
# 위에서 생성한 web-dep.yml이 적용된 상태여야 한다.
$ vi web-svc.yml
apiVersion: v1
kind: Service
metadata:
name: web-svc
spec:
type: NodePort
selector:
app: httpd
ports:
- nodePort: 31000
port: 80
targetPort: 80
$ kubectl apply -f web-svc.yml
# ip:NodePort에서 web이 배포된 것을 확인할 수 있다.
역할
Service는 Loadbalancer 역할을 한다. 이를 확인해보자.
$ vi web-dep.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-httpd-dep
spec:
replicas: 3
selector:
matchLabels:
app: httpd
template:
metadata:
name: my-httpd-pod
labels:
app: httpd
spec:
containers:
- name: httpd-container
image: 125.178.222.208:5000/ipnginx:latest # 수정!!
ports:
- containerPort: 80
로드밸런싱이 되는 것을 확인할 수 있다.
배포
hello world라는 index.html 파일을 포함하는 myhttpd라는 앱을 하나의 매니페스트 파일을 작성하여 배포해보자.
서비스이름: svc-httpd
서비스포트: 80
타겟포트: 80
노드포트: 32000
라벨 app: myhttpd
$ echo hello world > index.html
$ vi Dockerfile
FROM httpd:latest
ADD ./index.html /usr/local/apache2/htdocs/index.html
$ cat myhttpd.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myhttpd
spec:
replicas: 3
selector:
matchLabels:
app: myhttpd
template:
metadata:
labels:
app: myhttpd
spec:
containers:
- name: myhttpd
image: dahyeonn/myhttpd:1.1
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: svc-myhttpd
spec:
type: NodePort
selector:
app: myhttpd
ports:
- nodePort: 32000
port: 80
targetPort: 80
$ docker push dahyeonn/myhttpd:1.1
제대로 동작하는 것을 확인할 수 있다.
'🎆 Cloud Practice > 🧪 Docker, K8s, IaC' 카테고리의 다른 글
쿠버네티스 클러스터를 구축해보자 (온프레미스, kubeadm, v1.24) (0) | 2023.11.20 |
---|