[2023-06-03 금] Ingress, matallb, volume
1.
Ingress
- 앞서 service 로드밸런서는 L4(NLB)이고 인그레스는 L7(ALB)계층 로드밸런서다.
- 들어온 트래픽의 목적지 경로를 redirect해줌
- 클러스터 내의 서비스에 대한 외부 접근을 관리하는 API 오브젝트이며, 일반적으로 HTTP를 관리함.
- 인그레스는 부하 분산, SSL 종료, 명칭 기반의 가상 호스팅을 제공할 수 있다.
- 인그레스는 클러스터 외부에서 클러스터 내부 서비스로 HTTP와 HTTPS 경로를 노출한다. 트래픽 라우팅은 인그레스리소스에 정의된 규칙에 의해 컨트롤된다.
# docker ps # 프라이빗 리포지토리 떠있는지 컨테이너 확인
# yum install -y rdate
# rdate -s time.bora.net # 서버 시간 맞추기
# kubectl delete all --all
master 세션에서 실행
# echo 'alias k=kubectl' >> ~/.bashrc
# echo 'complete -F __start_kubectl k' >> ~/.bashrc
# yum install -y git
# git clone https://github.com/hali-linux/_Book_k8sInfra.git
# kubectl apply -f /root/_Book_k8sInfra/ch3/3.3.2/ingress-nginx.yaml # nginx가 제공하는 인그레스 스크립트
# kubectl get pods -n ingress-nginx # 스크립트로 생성된 인그레스 namespace에 있는 system pod가 생성되었다
2. ingress에서 사용할 이미지 생성
첫 번째 서비스 라우팅에는 DNS/foods 로 식품회사 food 페이지
두 번째 서비스 라우팅은 DNS/sales 로 sales 페이지
세 번째 서비스 라우팅은 회사 홈페이지
ingress와 서비스를 연결할 rule을 스크립트로 생성해야한다
도커 세션에서 이미지 만들기
# mkdir test-home && cd $_ # 도커 서버 세션에서 작업 공간 생성
# vi /etc/docker/daemon.json # 사설 리포지토리에 접근할 수 있도록 정보 등록
# systemctl restart docker
# docker pull 192.168.1.157:5000/nginx:latest # 사설 리포지토리에서 이미지 가져오기
이미지를 만들기 위해 tar파일로 만들 재료 업로드
# vi index.html # food 회사 웹페이지 만들기
# tar cvf food.tar index.html images # 하나의 tar파일로 묶음
# vi Dockerfile # 도커파일 생성
FROM 192.168.1.157:5000/nginx:latest # 도커 허브에서 가져오려면 FROM nginx:latest 으로 적으면 된다
ADD food.tar /usr/share/nginx/html
CMD ["nginx", "-g", "daemon off;"] # 생략 가능. nginx 이미지에 기본적으로 설정되어있음
FROM 192.168.1.157:5000/nginx:latest
ADD food.tar /usr/share/nginx/html
CMD ["nginx", "-g", "daemon off;"]
# docker build -t 192.168.1.157:5000/test-home:v1.0 . # 이미지 생성
# docker push 192.168.1.157:5000/test-home:v1.0 # 사설 리포지토리에 이미지 등록
# docker run -d -p 80:80 --name test-home 192.168.1.157:5000/test-home:v1.0 # 이미지를 이용해서 test-home 컨테이너를 생성+실행
접속테스트
# vi index.html # 배경색 green, sales-deploy로 변경
# tar cvf sale.tar images index.html
# vi Dockerfile # sale.tar로 변경
FROM 192.168.1.157:5000/nginx:latest
ADD sale.tar /usr/share/nginx/html
CMD ["nginx", "-g", "daemon off;"]
# docker build -t 192.168.1.157:5000/test-home:v2.0 .
# docker push 192.168.1.157:5000/test-home:v2.0
# vi index.html # 배경색 pink, home-deploy로 변경
# tar cvf home.tar images index.html
# vi Dockerfile # home.tar로 변경
FROM 192.168.1.157:5000/nginx:latest
ADD home.tar /usr/share/nginx/html
CMD ["nginx", "-g", "daemon off;"]
# docker build -t 192.168.1.157:5000/test-home:v0.0 .
# docker push 192.168.1.157:5000/test-home:v0.0
# docker images # 생성한 이미지 확인
pod에 들어갈 이미지는 다 준비가 되었다.
deployment yaml 스크립트로 service와 pod를 꾸밀 것이다.
deployment로 롤링업데이트, 복제가 수월함
master1 세션에서 실행
# mkdir ingress && cd $_
# kubectl get all # 현재 상태
# vi ingress-deploy.yaml # 인그레스 depolyment 스크립트
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: foods-deploy
spec:
replicas: 1
selector:
matchLabels:
app: foods-deploy
template:
metadata:
labels:
app: foods-deploy
spec:
containers:
- name: foods-deploy
image: 192.168.1.157:5000/test-home:v1.0
---
apiVersion: v1
kind: Service
metadata:
name: foods-svc
spec:
type: ClusterIP # 서비스를 ClusterIP를 주면서 pod를 외부로 노출시키지 않겠다는 뜻. 퍼블릭 IP을 드러내지 않기 때문
selector:
app: foods-deploy # deployment의 labels랑 매핑해줘야한다
ports:
- protocol: TCP
port: 80
targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: sales-deploy
spec:
replicas: 1
selector:
matchLabels:
app: sales-deploy
template:
metadata:
labels:
app: sales-deploy
spec:
containers:
- name: sales-deploy
image: 192.168.1.157:5000/test-home:v2.0
---
apiVersion: v1
kind: Service
metadata:
name: sales-svc
spec:
type: ClusterIP
selector:
app: sales-deploy
ports:
- protocol: TCP
port: 80
targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: home-deploy
spec:
replicas: 1
selector:
matchLabels:
app: home-deploy
template:
metadata:
labels:
app: home-deploy
spec:
containers:
- name: home-deploy
image: 192.168.1.157:5000/test-home:v0.0
---
apiVersion: v1
kind: Service
metadata:
name: home-svc
spec:
type: ClusterIP
selector:
app: home-deploy
ports:
- protocol: TCP
port: 80
targetPort: 80
# kubectl apply -f ingress-deploy.yaml # ingress-deploy 생성
# kubectl get all # 3개의 pod, 3개의 service, 3개의 deployment, 3개의 replicaset 생성된다
3.
ingress controller
# vi ingress-config.yaml # rule 기능을 하는 ingress controller pod 스크립트
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: ingress-nginx
annotations: # nginx에서 만든 ingress contrller를 사용한다. rewirete-target이란 프론트엔드에서 신호를 받아서 백엔드로 넘겨주는 것. '/'뒤에 붙는 rule에 따라 경로로 이동을 하게 해준다
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules: # 라우팅 규칙
- http:
paths: # 경로에 따라서 해당 service로 보내준다
- path: /foods
backend:
serviceName: foods-svc
servicePort: 80
- path: /sales
backend:
serviceName: sales-svc
servicePort: 80
- path: # 경로를 주지 않았을 때는 home으로 보내준다
backend:
serviceName: home-svc
servicePort: 80
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: ingress-nginx
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- http:
paths:
- path: /foods
backend:
serviceName: foods-svc
servicePort: 80
- path: /sales
backend:
serviceName: sales-svc
servicePort: 80
- path:
backend:
serviceName: home-svc
servicePort: 80
# kubectl apply -f ingress-config.yaml
# k get ingress ingress-nginx
# k get ingress ingress-nginx # 인그레스 상세 정보
# vi ingress-service.yaml # 제일 앞단에서 외부 트래픽을 받는 service 스크립트
apiVersion: v1
kind: Service
metadata:
name: nginx-ingress-controller
spec:
ports: # 외부 사용자가 접속해올 수 있는 포트 번호 지정
- name: http
protocol: TCP
port: 80
targetPort: 80
- name: https
protocol: TCP
port: 443
targetPort: 443
selector:
app.kubernetes.io/name: ingress-nginx # ingress controller pod로 매핑
type: LoadBalancer
externalIPs:
- 192.168.2.112 # mater1의 IP
apiVersion: v1
kind: Service
metadata:
name: nginx-ingress-controller
spec:
ports:
- name: http
protocol: TCP
port: 80
targetPort: 80
- name: https
protocol: TCP
port: 443
targetPort: 443
selector:
app.kubernetes.io/name: ingress-nginx
type: LoadBalancer
externalIPs:
- 192.168.2.112
# kubectl apply -f ingress-service.yaml
# kubectl get svc -n ingress-nginx -o wide
접속 테스트
4.
metallb metallb는 로드밸런서에게 externalip를 dhcp처럼 자동으로 부여하는 기능
# kubectl apply -f /root/_Book_k8sInfra/ch3/3.3.4/metallb.yaml # metallb 생성
# kubectl get pods -n metallb-system -o wide # 이미지를 못가져오고 있다. 도커허브에서 이미지를 지웠음
# vi metallb-l2config.yaml
apiVersion: v1
kind: ConfigMap # ConfigMap에 환경 설정 값을 저장해놨다가 다른 pod가 쉽게 참조할 수 있도록 함
metadata:
namespace: metallb-system
name: config
data: # 등록된 externalIP대역에서 IP를 pod에게 부여해준다
config: |
address-pools:
- name: nginx-ip-range
protocol: layer2
addresses:
- 192.168.2.113-192.168.2.114 # worker1, worker2의 IP
# kubectl apply -f metallb-l2config.yaml # metallb-l2config 생성
# kubectl describe configmaps -n metallb-system
// # kubectl delete -f metallb-l2config.yaml
# vi metallb-test.yaml # metallb의 pod, service 스크립트
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
labels:
app: nginx-pod
spec:
containers:
- name: nginx-pod-container
image: 192.168.1.157:5000/nginx.latest
---
apiVersion: v1
kind: Service
metadata:
name: loadbalancer-service-pod
spec:
type: LoadBalancer
# externalIPs:
# -
selector:
app: nginx-pod
ports:
- protocol: TCP
port: 80
targetPort: 80
# kubectl apply -f metallb-test.yaml
# kubectl delete -f metallb-test.yaml
5.
kubectl delete -f /root/_Book_k8sInfra/ch3/3.3.4/metallb.yaml
kubectl delete -f metallb-l2config.yaml
kubectl delete -f metallb-test.yaml
# docker pull bitnami/metallb-speaker:0.9.3
# docker pull bitnami/metallb-controller:0.9.3
# docker tag bitnami/metallb-speaker:0.9.3 192.168.1.157:5000/metallb-speaker:0.9.3
# docker tag bitnami/metallb-controller:0.9.3 192.168.1.157:5000/metallb-controller:0.9.3
# docker push 192.168.1.157:5000/metallb-speaker:0.9.3
# docker push 192.168.1.157:5000/metallb-controller:0.9.3
vi # 이미지 bitnami/metallb-speaker:0.9.3로 고치기. 두 군데
# vi /root/_Book_k8sInfra/ch3/3.3.4/metallb.yaml
/image로 검색해서 192.168.1.157:5000/metallb-speaker:0.9.3, 192.168.1.157:5000/metallb-controller:0.9.3 로 수정
# kubectl apply -f /root/_Book_k8sInfra/ch3/3.3.4/metallb.yaml
# kubectl get pod -n metallb-system -o wide
# kubectl apply -f metallb-l2config.yaml
# kubectl apply -f metallb-test.yaml
# kubectl get svc
# vi metallb-l2config.yaml
# kubectl apply -f metallb-12config.yaml
volume 관리 PV - persistent volume
컨테이너 내의 디스크에 있는 파일은 임시적이며, 컨테이너에서 실행될 때 애플리케이션에 적지 않은 몇 가지 문제가 발생합니다. 한 가지 문제는 컨테이너가 크래시될 때 파일이 손실된다는 것이다
k니belet은 컨테이너를 다시 시작하지만 초기화된 상태이다
두 번째 문제는 Pod에서 같이 실행되는 컨테이너 간에 파일을 공유할 때 발생한다
쿠버네티스는 다양한 유형의 볼륨을 지원합니다.
파드는 여러 볼륨 유형을 동시에 사용할 수 있습니다.
임시 볼륨 유형은 파드의 수명을 갖지만, 퍼시스턴트 볼륨(PV)은 파드의 수명을 넘어 존재한다.(영구 저장)
PV는 Pod 밖에 저장소를 만들어 놓았다.
PVC(Persistent Volume Claim) 은 pod가 PV에 얼만큼을 원하는지 요청하는 것. 그럼 PV가 원하는 만큼 떼어서 준다
1. PV 생성
2. PVC claim 생성 PV와 연결
3. pod 생성 PVC와 연결
6.
Volume
# mkdir volume && cd $_
# vi pv-pvc-pod.yaml
apiVersion: v1
kind: PersistentVolume # PV 세팅
metadata:
name: task-pv-volume
labels:
type: local # PV가 로컬
spec: # PV 세팅
storageClassName: manual # 온프레미스 환경 옵션값. 퍼블릭 Cloud 스토리지로 활용할 수 있다
capacity:
storage: 10Mi
accessModes:
- ReadWriteOnce # 보안상 한 곳에서만 접근할 수 있게 설정. 한 곳에서 연결되면 다른 곳 연결 차단
hostPath: # worker node의 경로
path: "/mnt/data"
---
apiVersion: v1
kind: PersistentVolumeClaim # PVC 세팅
metadata:
name: task-pv-claim
spec:
storageClassName: manual # 'manual'은 온프레미스 값. 퍼블릭 Cloud도 연결할 수 있다
accessModes:
- ReadWriteOnce # 보안상 한 곳에서만 접근
resources:
requests: # 요청하는 공간
storage: 1Mi
selector: # pv의 label을 찾아갈 수 있도록 pv의 labels로 매핑
matchLabels:
type: local # pv와 pvc 연결
---
apiVersion: v1
kind: Pod # pvc와 연결할 Pod 세팅
metadata:
name: task-pv-pod
labels:
app: task-pv-pod
spec:
volumes:
- name: task-pv-storage # Pod가 PV를 사용하겠다
persistentVolumeClaim:
claimName: task-pv-claim # Claim할 PVC 매핑
containers:
- name: task-pv-container
image: 192.168.1.157:5000/nginx:latest
ports:
- containerPort: 80
name: "http-server"
volumeMounts:
- mountPath: "/usr/share/nginx/html" # 컨테이너에 마운트할 경로. /mnt/data와 연결되는 위치
name: task-pv-storage # 마운트할 PVC와 매핑.
apiVersion: v1
kind: PersistentVolume
metadata:
name: task-pv-volume
labels:
type: local
spec:
storageClassName: manual
capacity:
storage: 10Mi
accessModes:
- ReadWriteOnce
hostPath:
path: "/mnt/data"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: task-pv-claim
spec:
storageClassName: manual
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Mi
selector:
matchLabels:
type: local
---
apiVersion: v1
kind: Pod
metadata:
name: task-pv-pod
labels:
app: task-pv-pod
spec:
volumes:
- name: task-pv-storage
persistentVolumeClaim:
claimName: task-pv-claim
containers:
- name: task-pv-container
image: nginx
ports:
- containerPort: 80
name: "http-server"
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: task-pv-storage
# kubectl apply -f pv-pvc-pod.yaml
worker1 세션에서 데이터 넣어두기
# echo "HELLO" > /mnt/data/index.html # 외부와 공유된다
master1 세션에서
# kubectl get svc
# kubectl expose pod task-pv-pod --name task-pv-pod --type=NodePort --port 80 # taks-pv-pod에게 노드포트를 준다. 클러스터 IP 포트 80
파드를 지워도 데이터가 남아있어야한다.
# kubectl delete pod task-pv-pod
# ls /mnt/data/ 안지워짐
master1 세션에서
파드 다시 만들기
# vi task-pv-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: task-pv-pod
labels:
app: task-pv-pod
spec:
volumes:
- name: task-pv-storage
persistentVolumeClaim:
claimName: task-pv-claim
containers:
- name: task-pv-container
image: 192.168.1.157:5000/nginx:latest
ports:
- containerPort: 80
name: "http-server"
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: task-pv-storage
# kubectl apply -f task-pv-pod.yaml # 파드 다시 생성
# kubectl get svc -o wide
# curl 10.100.121.255 # HELLO가 뜸. 지웠다가 다시 만들었는데도 마운트가 된다. PV, PVC만 보존이 되면 파드를 교체해도 데이터는 보존이 된다
# kubectl get pv, pvc # PV 용량 10Mi, ACCESS MODES RWO, Retain이란 PVC가 지워지더라도 데이터를 유지한다는 뜻. 옵션이 Delete로 되어있으면 PVC가 지워지면 PV 데이터도 날라간다
Bound는 PV와 PVC가 잘 연결되어있다는 뜻.
CLAIM은 어느 PVC와 연결되어있는지 알 수 있다
# kubectl delete pvc task-pv-claim # PVC 지우기
* rm -rf /mnt/data
* kubectl apply -f .
* echo "HELLO" > /mnt/data/index.html
* kubectl delete pod task-pv-pod
* kubectl delete pvc task-pv-claim
* Retain 동일한 스토리지 자산을 재사용하려는 경우, 동일한 스토리지 자산 정의로 새 퍼시스턴트볼륨을 생성한다.
7.
8.
# kubectl patch pvc pvc_name -p '{"metadata":{"finalizers":null}}' # 데이터 보호를 위해 delete로 못지움. patch로 pvc 지우기
# kubectl patch pv pv_name -p '{"metadata":{"finalizers":null}}' # pv 지우기
# kubectl patch pod pod_name -p '{"metadata":{"finalizers":null}}' # pod 지우기
metallb 수정
# vi metallb-l2config.yaml
# kubectl delete configmaps config -n metallb-system # 기존 것 지우기
# kubectl apply -f metallb-l2config.yaml
# kubectl get svc
# kubectl delete -f metallib-test.yaml
# vi metallb-test.yaml
# kubectl apply -f metallb-test.yaml # 새로 생성
# kubectl get pod, svc # metallb로 192.168.2.77 부여받았다
접속테스트
# vi metallb-test.yaml # name이랑 식별자를 2로 해서 pod를 새로 만든다
안바꼈네
kubectl get pod -n metallb-system # 파드 ID 확인
# kubectl logs -n metallb-system controller-78777cbb4b-dmmhl # 파드 로그 확인