L7 LB = ALB
인그레스를 구현하기 위한 컨트롤러
vagrant@k8s-node1 ~ kubectl api-resources | grep ingress
ingressclasses networking.k8s.io/v1 false IngressClass
ingresses ing networking.k8s.io/v1 true Ingress
vagrant@k8s-node1 ~ kubectl explain ing.spec
KIND: Ingress
VERSION: networking.k8s.io/v1
RESOURCE: spec <Object>
FIELDS:
defaultBackend <Object>
ingressClassName <string>
# ingressClasses 리소스
# 인그레스 컨트롤러 한개 지금(여러개 세팅가능)
# nginx naproxy apaceh 컨트롤러 여러개
# 하나하나를 클래스로 만들어 둘 수 있음
# 어떤 클래스를 가지고 만들 것 이냐
rules <[]Object>
# 라우팅 정책
tls <[]Object>
vagrant@k8s-node1 ~ kubectl explain ing.spec.rules
KIND: Ingress
VERSION: networking.k8s.io/v1
RESOURCE: rules <[]Object>
FIELDS:
host <string>
http <Object>
hostname을 포함하는 www.naver.com 도메인 www호스트 naver.com 도메인
와일드 카드도 가능 *foo.bar.com 앞에 뭐가 붙던 괜찮음
도메인은 실제로 존재해야함
vagrant@k8s-node1 ~ kubectl explain ing.spec.rules.http.paths
KIND: Ingress
VERSION: networking.k8s.io/v1
RESOURCE: paths <[]Object>
FIELDS:
backend <Object> -required-
path <string>
경로 기본적으로 지정안하면 `/` 원한다면 info -> /info
PathType with value "Exact" or "Prefix".
pathType <string> -required-
# Exact 정확히 일치 # Prefix 일부분만 일치
ImplementationSpecific
# 이 경로 유형의 일치 여부는 IngressClass에 따라 달라짐.
# 구현할 때 별도 pathType 으로 처리하거나, Prefix 또는 Exact 경로 유형과 같이 동일하게 처리할 수 있음
service
어떤종류의 리소스이냐
apiGroup <string>
APIGroup is the group for the resource being referenced. If APIGroup is not
specified, the specified Kind must be in the core API group. For any other
third-party types, APIGroup is required.
kind <string> -required-
Kind is the type of resource being referenced
name <string> -required-
Name is the name of resource being referenced
실제 연결하고자 하는 서비스 rule정책을통해 서비스로 연결할 것인가
vagrant@k8s-node1 ~ kubectl explain ing.spec.rules.http
KIND: Ingress
VERSION: networking.k8s.io/v1
RESOURCE: http <Object>
FIELDS:
paths <[]Object> -required-
순서가 중요
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-wildcard-host
spec:
rules:
- host: "foo.bar.com"
http:
paths:
- pathType: Prefix
path: "/bar"
backend:
service:
name: service1
port:
number: 80
- host: "*.foo.com"
http:
paths:
- pathType: Prefix
path: "/foo"
backend:
service:
name: service2
port:
number: 80
순서 바꾸면 foo.bar.com은 정책연결이 안됨
노드포트 만들어서 라우팅 시키기. 경로는 프리픽스에 루트로 지정
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myweb-ing
spec:
rules:
- host: '*.encore.xyz'
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: myweb-svc-np
port:
number: 80 # 클러스터 IP의 포트
curl http://192.168.100.100 -v
> 이건 요청이라는뜻
< 이건 응답이라는뜻
kubectl get all 에는 ingress 리소스는 포함되어 있지 않음
kubectl get ing
모든 호스트의 ip가 찍힘 ALB를 쓰면 ALB주소 하나
kubetctl get po -n ingress-nginx
컨트롤러가 모든 노드에 하나씩 다 떠있음
얘들이 L7 로드밸런서 역할을 하고 각노드 아무데나 접속해도 가능
ALB는 하나만 잇을텐데 얘는 모든노드에 걸쳐서 다 만들어져 있어서 어떤노드로 들어와도 상관없음
방법1
curl --resolve www.encore.xyz:80:192.168.100.100 http://www.encore.xyz
방법2
/etc/hosts
...
192.168.100.100 www.encore.xyz
curl http://www.encore.xyz
방법3
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myweb-ing
spec:
rules:
- host: '*.nip.io'
...
kubectl replace -f myweb-ing.yaml
curl http://192-168-100-100.nip.io
hello:one 이미지
Dockerfile
FROM httpd
COPY index.html /usr/local/apache2/htdocs/index.html
index.html
<h1> Hello One </h1>
hello:two 이미지
Dockerfile
FROM httpd
COPY index.html /usr/local/apache2/htdocs/index.html
index.html
<h1> Hello Two </h1>
docker image build X/hello:one
docker image build X/hello:two
docker login
docker push X/hello:one
docker push X/hello:two
containerd는 이미지 빌드하는 기능은 없음
aws codebuild
소스코드 컴파일, 도커이미지 빌드하는 용도
github action 이미지를 빌드
buildah https://buildah.io/
podman by redhat 컨테이너 실행
buildah by redhat 이미지 빌드
skopeo 원격 레포지토리를 관리
RS
one-rs.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: one-rs
spec:
replicas: 3
selector:
matchLabels:
app: hello-one
template:
metadata:
labels:
app: hello-one
spec:
containers:
- name: hello-one
image: c1t1d0s7/hello:one
ports:
- containerPort: 80
protocol: TCP
two-rs.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: two-rs
spec:
replicas: 3
selector:
matchLabels:
app: hello-two
template:
metadata:
labels:
app: hello-two
spec:
containers:
- name: hello-two
image: c1t1d0s7/hello:two
ports:
- containerPort: 80
protocol: TCP
one-svc-np.yaml
apiVersion: v1
kind: Service
metadata:
name: one-svc-np
spec:
type: NodePort
selector:
app: hello-one
ports:
- port: 80
targetPort: 80
two-svc-np.yaml
apiVersion: v1
kind: Service
metadata:
name: two-svc-np
spec:
type: NodePort
selector:
app: hello-two
ports:
- port: 80
targetPort: 80
hello-ing.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: hello-ing
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
# URL 재작성, /one -> /, /two -> / -> 쓰지않으면 ip/one처럼 붙기 때문에 에러
spec:
rules:
- host: '*.nip.io'
http:
paths:
- path: /one
pathType: Prefix
backend:
service:
name: one-svc-np
port:
number: 80
- path: /two
pathType: Prefix
backend:
service:
name: two-svc-np
port:
number: 80
kubectl create -f .
파드의 헬스체크를 통해 서비스의 엔드포인트 리소스에 타겟 등록
->
애플리케이션의 정상확동을 확인하여 엔드포인트에 등록을 시켜주는 개념 건강상태를 체크해서 앱이 정상작동하면 엔드포인트에 등록 비정상이면 등록을 안해서 라우팅을 안하도록 해주는
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: myweb-rs
spec:
replicas: 3
selector:
matchLabels:
app: web
env: dev
template:
metadata:
labels:
app: web
env: dev
spec:
containers:
- name: myweb
image: ghcr.io/c1t1d0s7/go-myweb:alpine
ports:
- containerPort: 8080
protocol: TCP
readinessProbe:
exec:
command:
- ls
- /tmp/ready
# 이파일은 없음 -> 프로브 실패
# 파일이 생성되면 정상 작동
apiVersion: v1
kind: Service
metadata:
name: myweb-svc-lb
spec:
type: LoadBalancer
selector:
app: web
ports:
- port: 80
targetPort: 8080
kubectl create -f .
watch -n1 -d kubectl get po,svc,ep
kubectl exec <POD> -- touch /tmp/ready
파드 데이터 저장 불가 -> 저장 가능하지만 컨테이너 지우면 지워짐 -> 컨테이너에 볼륨을 생성가능
spec.volumes.*
: 볼륨 유형
볼륨 유형들을 나열
https://kubernetes.io/ko/docs/concepts/storage/volumes/#volume-types
임시로 사용할 빈 볼륨, 파드 삭제 시 볼륨 같이 삭제
apiVersion: v1
kind: Pod
metadata:
name: myweb-pod
spec:
containers:
- name: myweb1
image: httpd
volumeMounts:
- name: emptyvol
mountPath: /empty # 디렉토리 없으면 자동 생성
- name: myweb2
image: ghcr.io/c1t1d0s7/go-myweb:alpine
volumeMounts:
- name: emptyvol # volumes.name과 매칭
mountPath: /empty # 어디에 마운트할 지
volumes:
- name: emptyvol
emptyDir: {} # {} -> 설정없음
kubectl exec -it myweb-pod -c myweb1 -- bash
> cd /empty
> touch a b c
kubectl exec -it myweb-pod -c myweb2 -- sh
> ls /empty
디폴트는 디스크, 메모리도 지정가능(고속의 임시스토리지)
emptyDir은 임시디렉토리, 파드의 라이프타임까지 공유 -> 파드지우면 같이 지워짐
readOnly지정 가능. 지정하지 않으면 RW
readOnly <boolean>
Mounted read-only if true, read-write otherwise (false or unspecified).
Defaults to false.
Pod 생성될때 딱한번만 실행됨 -> 실행하고 종료
-> 초기화 컨테이너 종료가 되는 앱이여야함
https://kubernetes.io/ko/docs/concepts/workloads/pods/init-containers/
apiVersion: v1
kind: Pod
metadata:
name: init-pod
spec:
initContainers:
- name: gitpull
image: alpine/git
args:
- clone # git에서 코드를 가져옴
- -b
- v2.18.1
- https://github.com/kubernetes-sigs/kubespray.git
- /repo
volumeMounts:
- name: gitrepo
mountPath: /repo
containers:
- name: gituse
image: busybox
args:
- tail # 셸 계속해서 실행하기 위한 꼼수 tail -f /dev/null
- -f
- /dev/null
volumeMounts:
- name: gitrepo
mountPath: /kube # /kube디렉토리로 파일들이 복사가 됨
volumes:
- name: gitrepo
emptyDir: {}
gitclone 하고 종료되고 busybox가 저장을 함
https://hub.docker.com/r/alpine/git
알파인 git 알파인리눅스에 git을 포함 시켜뒀음
도커의 바인드방식와 비슷
특정경로를 컨테이너의 볼륨을 제공
vagrant@k8s-node1 ~/volume/hostPath kubectl explain pods.spec.volumes.hostPath
KIND: Pod
VERSION: v1
RESOURCE: hostPath <Object>
FIELDS:
path <string> -required-
type <string>
/mnt/web_contents/index.html
<h1> Hello hostPath </h1>
참고
로컬 스토리지: 다른 호스트에 스토리지 볼륨을 제공할 수 X
- emptyDir
- hostPath
- gitRepo
- local
httpd 이미지를 가지고 RS를 만들어보기
복제본은 3개
모든 컨테이너 접근할때 똑같은게 보여야함
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: myweb-rs-hp
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: myweb
image: httpd
volumeMounts:
- name: web-contents
mountPath: /usr/local/apache2/htdocs/
volumes:
- name: web-contents # 이름 언더바 불가능
hostPath:
type: Directory
path: /web_contents
node1에 있는 파드가 정상실행인데
나머지는 제대로 만들어지고 있지 않음 -> 노드2, 3에는 web_contest 디렉토리가 없기때문
pod만들어지는 순서 볼륨을 지정하니까 스케쥴링이되고 해당되는 볼륨이 있는지 먼저 체크를 함
볼륨이 잇으면 이미지를 풀링함
그리고 컨테이너를 크리에이트
-----> emptyDir, hostPath -> local 스토리지 로컬에 있는 파드에 제공 가능
네트워크 넘어서 파드에 제공 가능은 불가 -> 네트워크 스토리지가 아님
루트밑에 디렉토리만드는건 루트 권한만
파일 sudo 해도 안먹힘
> 입력이니까 안먹힘sudo 는 echo에만
권한이 없는 디렉토리에 파일을 생성하는이 불가능
tee라는 명령어
sudo tee -> cat랑 비슷
echo "hello world" | sudo tee /a/a.txt
지금까지는 파드의 직접 볼륨을 붙임
파드와 스토리지(볼륨)의 구역을 분리하기 위함
Pod
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: mypod
image: httpd
volumeMounts:
- name: myvol
mountPath: /tmp
volumes:
- name: myvol
persistentVolumeClaim:
name: mypvc # pvc의 이름으로 요청하여 PV와 연결
PVC
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mypvc
spec:
volumeName: mypv
...
PV
apiVersion: v1
kind: PersistentVolume
metadata:
name: mypv
spec:
hostPath:
path: /web_contents
type: DirectoryOrCreate
PV <--1:1--> PVC 무조건 1대1연결만 가능
스토리지에 따라서 지원되는 명령이 다름
기본적인 원칙은 블록스토리지(DAS)냐 네트워크 스토리지냐
네트워크 스토리지는
node1: NFS 서버
sudo apt install nfs-kernel-server -y
sudo mkdir /nfsvolume
echo "<h1> Hello NFS Volume </h1>" | sudo tee /nfsvolume/index.html
sudo chown -R www-data:www-data /nfsvolume
/etc/exports
/nfsvolume 192.168.100.0/24(rw,sync,no_subtree_check,no_root_squash)
sudo systemctl restart nfs-kernel-server
systemctl status nfs-kernel-server
node1, node2, node3
sudo apt install nfs-common -y
또는
ansible all -i ~/kubespray/inventory/mycluster/inventory.ini -m apt -a 'name=nfs-common' -b
PV
apiVersion: v1
kind: PersistentVolume
metadata:
name: mypv
spec:
accessModes:
- ReadWriteMany
capacity:
storage: 1G
persistentVolumeReclaimPolicy: Retain
nfs:
path: /nfsvolume
server: 192.168.100.100
PVC
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mypvc
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1G
storageClassName: '' # storageClassName 동적 프로비저닝을 해줌 안할거면 비워놔야함
# ''로 비워놓기
volumeName: mypv
RS
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: myweb-rs
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: myweb
image: httpd
volumeMounts:
- name: myvol
mountPath: /usr/local/apache2/htdocs
volumes:
- name: myvol
persistentVolumeClaim:
claimName: mypvc
SVC
apiVersion: v1
kind: Service
metadata:
name: myweb-svc-lb
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 80
selector:
app: web