- 관리자가 볼륨제공, 요청을 동시에 수행한다.
- 관리자는 포드구성 및 포드내에 저장소의 위치(IP), 디렉토리 명 등을 정확히 알고 있어야 한다.
- PVC 는 개발자가, PV 는 관리자가 작성한다.
- PVC 는 볼륨이 어떤형태로 제공되는지(nfs? iscsi?..) 몰라도 된다. 단지, 자신이 필요한 볼륨의 유형과 크기만 작성하면 된다. (rw!, ro!, one to one , many to one, 1g, 10g)
- PV 는 관리자가 nfs, iscsi 등을 이용하여 적절한 크기의 볼륨을 만들어 이를 pool 에 보관한다.
root@manager:~/k8slab# echo $KUBECONFIG /etc/kubernetes/admin.conf <-- 쿠버네티스 전체 관리자 admin
- KUBECONFIG 는 service account 의 정보를 누구로 할 것인지 파일을 지정하는 변수
- 현재 위치 파일의 pod 모두 삭제
root@manager:~/k8slab# kubectl delete -f .
kubectl get pod kubectl get svc
- master 노드에 NFS 마운트를 위한 서버 설치
root@master:~# apt-get -y install nfs-server
root@master:~# systemctl status nfs-server | grep Active Active: active (exited) since Thu 2022-03-31 08:39:45 KST; 10s ago
root@master:~# mkdir -p ~/pvpvc/shared
root@master:~# chmod 777 pvpvc/shared/
root@master:~# vi /etc/exports root@master:~# # 아래 내용을 추가 /root/pvpvc/shared *(rw,no_root_squash,sync) no_root_squash -> 외부 노드에서 작성한 파일을 로컬(nfs-server) 에서 확인했을 때 root 가 작성한것으로(소유주가 root) 간주해 준다.
root@master:~# ufw disable Firewall stopped and disabled on system startup
root@master:~# systemctl enable nfs-server --now
root@master:~# systemctl restart nfs-server
- 생성된 공유저장소 마운트를 위한 포드배포
root@master1:~/k8s# cat nfs-pod.yaml apiVersion: v1 kind: Pod metadata: name: nfs-pod spec: containers: - name: nfs-mount-container image: busybox args: [ "tail", "-f", "/dev/null" ] volumeMounts: - name: nfs-volume mountPath: /mnt # 포드 컨테이너 내부의 /mnt 디렉터리에 마운트합니다. volumes: - name : nfs-volume nfs: # NFS 서버의 볼륨을 포드의 컨테이너에 마운트합니다. path: /root/pvpvc/shared # 변경해야 함 server: 211.183.3.100 # 변경해야 함
- Pod에서 nfs 서버에 직접접속하는 것이 아니라 노드에서 접속하게 되므로 node1~node3
에 nfs 클라이언트 설치root@node1:~# apt-get -y install nfs-common root@node2:~# apt-get -y install nfs-common root@node3:~# apt-get -y install nfs-common
- Pod 배포와 마운트 확인
root@master:~/pvpvc# cat nfs-pod.yaml apiVersion: v1 kind: Pod metadata: name: nfs-pod spec: containers: - name: nfs-mount-container image: nginx volumeMounts: - name: nfs-volume mountPath: /mnt volumes: - name: nfs-volume nfs: path: /root/pvpvc/shared server: 211.183.3.100 root@master:~/pvpvc# kubectl apply -f nfs-pod.yaml root@master:~/pvpvc# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE ... nfs-pod 1/1 Running 0 8s 192.168.166.141 node1 ... root@master:~/pvpvc# kubectl exec nfs-pod -- ls /mnt root@master:~/pvpvc# touch /root/pvpvc/shared/nfscheck.txt # nfs-server 에 파일 생성 root@master:~/pvpvc# kubectl exec nfs-pod -- ls /mnt # pod 에서 확인 nfscheck.txt
- 기본적으로 nfs 의 공유 저장소에 외부 사용자가 접속하여 파일을 생성하게 되면 이 소유주는 "nfsnobody" 로 작성된다. 하지만 /etc/exports 에 no_root_squash 가 옵션으로 작성되어 있다면 외부 사용자가 파일을 생성하더라도 root 로 기록된다.
- PV 생성
root@master:~/pvpvc# cat nfs-pv.yaml apiVersion: v1 kind: PersistentVolume metadata: name: nfs-pv spec: capacity: storage: 1Gi accessModes: - ReadWriteMany persistentVolumeReclaimPolicy: Retain nfs: path: /root/pvpvc/shared server: 211.183.3.100 readOnly: false
root@master:~/pvpvc# kubectl apply -f nfs-pv.yaml persistentvolume/nfs-pv created
root@master:~/pvpvc# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE nfs-pv 1Gi RWX Retain Available 5s
- pvc, pod 생성과 생성된 pv 와의 연결상태 확인
root@master:~/pvpvc# cat nfs-pod-pvc.yaml apiVersion: v1 kind: PersistentVolumeClaim metadata: name: my-nfs-pvc spec: storageClassName: "" accessModes: - ReadWriteMany resources: requests: storage: 1Gi --- apiVersion: v1 kind: Pod metadata: name: nfs-mount-container spec: containers: - name: nfs-mount-container image: nginx volumeMounts: - name: nfs-volume mountPath: /mnt volumes: - name: nfs-volume persistentVolumeClaim: claimName: my-nfs-pvc root@master:~/pvpvc# kubectl apply -f nfs-pod-pvc.yaml persistentvolumeclaim/my-nfs-pvc created pod/nfs-mount-container created root@master:~/pvpvc# root@master:~/pvpvc# kubectl get pv,pvc NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE persistentvolume/nfs-pv 1Gi RWX Retain Bound default/my-nfs-pvc 6m51s NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE persistentvolumeclaim/my-nfs-pvc Bound nfs-pv 1Gi RWX 9s
root@master:~/pvpvc# kubectl get pod | grep nfs-mount nfs-mount-container 1/1 Running 0 29s
root@master:~/pvpvc# kubectl exec nfs-mount-container -- df | grep /mnt 211.183.3.100:/root/pvpvc/shared 19992576 11765248 7188480 63% /mnt root@master:~/pvpvc# # volume 이 아닌 nfs를 사용하고 있어 1G 로 표시되지는 않음
[실습]
- 211.183.3.100 에 nfs-server 를 구축한다
- manager 에 /shared 디렉토리를 생성하고 퍼미션을 777 로 조정한다.
- /etc/exports 에 /shared 를 외부에 공개하도록 설정한다.
단, 포드에서만 접속이 가능하도록 해야 한다. 어떤주소를 허용해야 하는가?/shared 211.183.3.0/24(rw,no_root_squash,sync)
- nfs-server 활성화/실행
- 위의 pod 구성을 위한 매니페스트 파일을 참고하여 포드3개를 배포하고 포드의 /mnt 를 nfs-server 의 /shared 와 마운트한다.
- manager 에서 /shared 에 임의 파일(test.txt)을 생성하고 포드에서 exec 를 활용하여 해당 파일을 볼 수 있어야 한다. 단 모든 포드에서 볼 수있어야 한다.
선결조건
- metallb 가 준비된 상태이어야 한다. on-premise 환경에서 사용하기 어려운 service type LoadBalancer 를 포드 형태로 제공할 수 있는 방법
- 각 LB 별로 필요한 구성값을 추가하여 배포해야 한다.
- 생성된 포드에 볼륨을 연결할 계획이므로 master 에 nfs 서버가 구축되어 있어야 한다.
(상태확인, 마운트 가능여부 확인을 위해 , node 에서 showmount -e 211.183.3.100)시나리오.
- 우리는 kia, sk 의 서비스(서비스(nodeport/lb), deployment, volume) 을 관리해 주는 업체이다
- kia, sk 는 별도의 ns , address-pool on LB, mount point
1. nfs
- nfs 에서의 구성
root@manager:~/k8slab# systemctl status nfs-server | grep Active Active: active
- 모든 파일과 디렉터리 권한을 777로 부여
root@manager:~/k8slab# mkdir /kia /sk root@manager:~/k8slab# chmod 777 /sk -R root@manager:~/k8slab# chmod 777 /kia -R
root@manager:~/k8slab# tail -2 /etc/exports /kia 211.183.3.0/24(rw,sync,no_root_squash) /sk 211.183.3.0/24(rw,sync,no_root_squash)
root@manager:~/k8slab# systemctl restart nfs-server
- [확인@worker1~3]
root@worker2:~# showmount -e 211.183.3.100 Export list for 211.183.3.100: /sk 211.183.3.0/24 /kia 211.183.3.0/24 /shared 211.183.3.0/24
- 파일 생성
root@manager:~/k8slab# mkdir lab1; cd lab1 root@manager:~/k8slab/lab1# touch kia-ns.yaml sk-ns.yanl
2. namespace
- ns 버전 확인
root@manager:~/k8slab/lab1# kubectl api-resources | grep Name namespaces ns v1 false Namespace
- namespace 생성
root@manager:~/k8slab/lab1# cat kia-ns.yaml apiVersion: v1 kind: Namespace metadata: name: kia
root@manager:~/k8slab/lab1# kubectl create ns kia
- namespace 생성
root@manager:~/k8slab/lab1# cat sk-ns.yaml apiVersion: v1 kind: Namespace metadata: name: sk
root@manager:~/k8slab/lab1# kubectl create ns sk
3. ConifMap
- metalLB를 이용하여 사용하게 될 LB 주소 지정하기
default : 211.183.3.201 - 211.183.3.210 kia : 211.183.3.211 - 211.183.3.220 sk : 211.183.3.221 - 211.183.3.230
- 버전 확인
root@manager:~/k8slab/lab1# kubectl api-resources | grep ConfigMap configmaps cm v1 true ConfigMap
root@manager:~/k8slab/lab1# cat lb-config.yaml apiVersion: v1 kind: ConfigMap metadata: namespace: metallb-system name: config data: config: | address-pools: - name: default protocol: layer2 addresses: - 211.183.3.201-211.183.3.210 - name: kia protocol: layer2 addresses: - 211.183.3.211-211.183.3.220 - name: sk protocol: layer2 addresses: - 211.183.3.221-211.183.3.230
- metallb 의 config 부분에 data 를 하나로 보내기 위해 | 사용
root@manager:~/k8slab/lab1# touch kia-deploy-svc.yaml sk-deploy-svc.yaml
root@manager:~/k8slab/lab1# cat kia-deploy-svc.yaml apiVersion: apps/v1 kind: Deployment metadata: namespace: kia name: kia-deploy spec: strategy: # repliacas type: Recreate replicas: 3 selector: matchLabels: app: kia template: # POD metadata: labels: app: kia spec: #container containers: - name: kia-nginx image: nginx ports: - containerPort: 80
- 배포하기
root@manager:~/k8slab/lab1# kubectl apply -f kia-deploy-svc.yaml
- 확인하기
root@manager:~/k8slab/lab1# kubectl get pod NAME READY STATUS RESTARTS AGE hpa-hname-pods-6df6f77d64-pz57p 1/1 Running 1 18h
root@manager:~/k8slab/lab1# kubectl get pod -n kia NAME READY STATUS RESTARTS AGE kia-deploy-5fcb8b68db-4pwpl 1/1 Running 0 17s kia-deploy-5fcb8b68db-j2xsw 1/1 Running 0 17s kia-deploy-5fcb8b68db-xf9vn 1/1 Running 0 17s
4. 각 회사별 deploy-svc 생성/배포하기
참고 : https://metallb.universe.tf/usage/
5. deploy 배포시 kia와 sk의 모든 포드는 각 포드의 /test 디렉토리를 각각 nfs 서버의 /kia, /sk 와 마운트되어야 한다.
- 확인해야 할 사항
kubectl exec [포드이름] -n kia -- ls /test kia.txt
- kia NFS 설정 및 확인
apiVersion: apps/v1 kind: Deployment metadata: #deployment namespace: kia name: kia-deploy spec: #replicaset replicas: 3 strategy: type: Recreate selector: matchLabels: app: kia template: #pod metadata: labels: app: kia spec: #container containers: - name: kia-nginx image: nginx ports: - containerPort: 80 volumeMounts: - name: kia-vol mountPath: /test volumes: - name: kia-vol nfs: path: /kia server: 211.183.3.100 --- apiVersion: v1 kind: Service metadata: name: nginx namespace: kia annotations: metallb.universe.tf/address-pool: kia spec: ports: - port: 80 targetPort: 80 selector: app: kia type: LoadBalancer
root@manager:~/k8slab/lab1# kubectl apply -f kia-deploy-svc.yaml
root@manager:~/k8slab/lab1# kubectl get pod -n kia
root@manager:~/k8slab/lab1# kubectl exec kia-deploy-5ccc6dc745-2nmd7 -n kia -- ls /test kia.txt
① nginx 인그레스 서비스 환경 구현
- lb-ingress-service
root@manager:~/k8slab/lab2# vi ingress-config.yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: ingress-nginx annotations: nginx.ingress.kubernetes.io/rewrite-target: / kubernetes.io/ingress.class: "nginx" spec: rules: - http: paths: - path: / pathType: Prefix backend: service: name: default port: number: 80 - path: /shop pathType: Prefix backend: service: name: shop port: number: 80 - path: /blog pathType: Prefix backend: service: name: blog port: number: 80
- 인그레스 컨트롤러 배포
root@manager:~/k8slab/lab2# kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.1.2/deploy/static/provider/cloud/deploy.yaml
- 포드 배포
root@manager:~/k8slab/lab2# touch shop-deploy-svc.yaml
root@manager:~/k8slab/lab2# touch blog-deploy-svc.yaml
root@manager:~/k8slab/lab2# touch default-deploy-svc.yaml
- yaml 파일 구성
root@manager:~/k8slab/lab2# vi shop-deploy-svc.yaml root@manager:~/k8slab/lab2# cat shop-deploy-svc.yaml > default-deploy-svc.yaml root@manager:~/k8slab/lab2# vi default-deploy-svc.yaml root@manager:~/k8slab/lab2# cat shop-deploy-svc.yaml > blog-deploy-svc.yaml root@manager:~/k8slab/lab2# sed -i 's/shop/blog/g' blog-deploy-svc.yaml root@manager:~/k8slab/lab2# sed -i 's/nginx/httpd/g' blog-deploy-svc.yaml root@manager:~/k8slab/lab2# sed -i 's/30001/30002/g' blog-deploy-svc.yaml
root@manager:~/k8slab/lab2# cat default-apiVersion: apps/v1 kind: Deployment metadata: name: default spec: replicas: 3 selector: matchLabels: app: default template: metadata: name: default labels: app: default spec: containers: - name: default image: nginx ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: default spec: ports: - name: default-port port: 80 # service's port targetPort: 80 # Pod's Port nodePort: 30000 selector: app: default type: NodePort
root@manager:~/k8slab/lab2# cat shop-deploy-svc.yaml apiVersion: apps/v1 kind: Deployment metadata: name: shop spec: replicas: 3 selector: matchLabels: app: shop template: metadata: name: shop labels: app: shop spec: containers: - name: shop image: nginx ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: shop spec: ports: - name: shop-port port: 80 # service's port targetPort: 80 # Pod's Port nodePort: 30001 selector: app: shop type: NodePort
root@manager:~/k8slab/lab2# cat blog-deploy-svc.yaml apiVersion: apps/v1 kind: Deployment metadata: name: blog spec: replicas: 3 selector: matchLabels: app: blog template: metadata: name: blog labels: app: blog spec: containers: - name: blog image: httpd ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: blog spec: ports: - name: blog-port port: 80 # service's port targetPort: 80 # Pod's Port nodePort: 30002 selector: app: blog type: NodePort
- 현재까지 내용을 확인하기 위한 방법
master/manager에서 curl을 이용하여 노드 포트를 통해 각 포드에 접속할 수 있는지 여부를 확인한다. 이는 클러스터 환경 외부(인터넷)에서의 접속을 확인하는 것은 아니고 내부적으로 정상 동작 여부를 확인하기 위한 것이다.root@manager:~/k8slab/lab2# curl http://211.183.3.101:30000
root@manager:~/k8slab/lab2# curl http://211.183.3.101:30001
root@manager:~/k8slab/lab2# curl http://211.183.3.101:30002
root@manager:~/k8slab/lab2# kubectl get ing NAME CLASS HOSTS ADDRESS PORTS AGE ingress-nginx <none> * 211.183.3.201 80 38m
추가 요구
아래와 같은 요구 사항을 적용시키자
/ - default - Pod : 10 ~ 15 0.25/16m /blog - blod - Pod : 5 ~ 10 0.25/16m /shop - shop - Pod : 10 ~ 20 0.5/32m
- 최종적으로 우리 회사 DNS 서버에 아래의 정보를 등록시켜야 한다
- test.com -> zone file 파일 -> test.com.db 에 등록해야 한다
- 도메인이 test.com 일 때, hong IN A 211.183.3.201 로 등록하면 hong.test.com 에 접속시 211.183.3.201 에 접속된다
- 별도 도메인을 구매하여 해당 도메인과 211.183.3.201 을 매핑하는 방법도 있다
각각의 페이지는 configmap 을 이용하여 붙여넣기 해 보세요!!! default(nginx) -> https://www.naver.com/ shop(nginx) -> https://www.coupang.com/ blog(httpd) -> https://www.kakaocorp.com/
ingress
- ingress-config.yaml
root@manager:~/k8slab/lab2# cat ingress-config.yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: ingress-nginx annotations: nginx.ingress.kubernetes.io/rewrite-target: / kubernetes.io/ingress.class: "nginx" spec: rules: - http: paths: - path: / pathType: Prefix backend: service: name: default port: number: 80 - path: /shop pathType: Prefix backend: service: name: shop port: number: 80 - path: /blog pathType: Prefix backend: service: name: blog port: number: 80
kubectl apply -f ingress-config.yaml
default
curl -L http://www.naver.com > index.html
kubectl create cm defaultcm --from-file index.html
root@manager:~/k8slab/lab2# cd default root@manager:~/k8slab/lab2/default# vi default-deploy-svc.yaml
root@manager:~/k8slab/lab2/default# cat default-deploy-svc.yaml apiVersion: apps/v1 kind: Deployment metadata: name: default spec: replicas: 3 selector: matchLabels: app: default template: metadata: name: default labels: app: default spec: containers: - name: default image: nginx ports: - containerPort: 80 volumeMounts: - name: defaultvol mountPath: /usr/share/nginx/html volumes: - name: defaultvol configMap: name: defaultcm
kubectl apply -f default-deploy-svc.yaml
shop
curl -L https://www.coupang.com/ > index.html
kubectl create cm shopcm --from-file index.html
root@manager:~/k8slab/lab2# cd shop root@manager:~/k8slab/lab2/shop# vi shop-deploy-svc.yaml
root@manager:~/k8slab/lab2/shop# cat shop-deploy-svc.yaml apiVersion: apps/v1 kind: Deployment metadata: name: shop spec: replicas: 3 selector: matchLabels: app: shop template: metadata: name: shop labels: app: shop spec: containers: - name: shop image: nginx ports: - containerPort: 80 volumeMounts: - name: shopvol mountPath: /usr/share/nginx/html volumes: - name: shopvol configMap: name: shopcm
kubectl apply -f shop-deploy-svc.yaml
blog
curl -L https://www.kakaocorp.com/ > index.html
kubectl create cm blogcm --from-file index.html
root@manager:~/k8slab/lab2# cd blog root@manager:~/k8slab/lab2/blog# vi blog-deploy-svc.yaml
root@manager:~/k8slab/lab2/blog# cat blog-deploy-svc.yaml apiVersion: apps/v1 kind: Deployment metadata: name: blog spec: replicas: 3 selector: matchLabels: app: blog template: metadata: name: blog labels: app: blog spec: containers: - name: blog image: httpd ports: - containerPort: 80 volumeMounts: - name: blogvol mountPath: /usr/local/apache2/htdocs/ volumes: - name: blogvol configMap: name: blogcm
kubectl apply -f blog-deploy-svc.yaml
- 일반적인 사용방법은 configMap 거의 동일하지만, 저장된 secret 을 describe 를 통해 확인할 수는 없다.
- ssh, key, 인증서, username/password 등을 Pod 내에 전달할 때 주로 사용한다.
- 사설 저장소를 사용하는 경우 각 노드는 사설 저장소로 접속하기 위한 인증정보를 보유하고 있어야 한다. 인증정보에 포함되는 요소들은 username, password, 저장소의 주소
[docker hub]
docker login user: pass:
docker login https://reg.test.com username: password:
- secret 은 노드간 통신에서는 보이지 않지만 포드내에서는 clear text 로 확인이 된다.
https://kubernetes.io/ko/docs/tasks/configure-pod-container/pull-image-private-registry/
- 도커 허브로의 로그인을 위한 secret 생성하기와 지정된 저장소 주소로의 접속을 위한 secret
생성하기kubectl create secret docker-registry regcred --docker-server=<your-registry-server> --docker-username=<your-name> --docker-password=<your-pword> --docker-email=<your-email>
kubectl create secret generic dockerhub1 \ --from-file=.dockerconfigjson=/root/.docker/config.json \ --type=kubernetes.io/dockerconfigjson
docker-registry -> 현재 만드는 secret 은 일반적인 generic 이 아니라 도커 저장소에 접속을 위한 secret 으로 사용된다.(type 지정)
regcred -> secret 이름
--docker-server=사설저장소주소
[활용]apiVersion: v1 kind: Pod metadata: name: private-reg spec: containers: - name: test-oracle image: oraclelinux:latest imagePullSecrets: - name: dockerhub1