kubectl exec <컨테이너 이름> -- sh -c "echo '<h1>WEB01</h1>' > /usr/share/nginx/html/index.html"
# kubeadm reset
# kubeadm init --apiserver-advertise-address=master ip --pod-network-cidr=10.244.0.0/16
# mkdir -p $HOME/.kube
# cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
# chown $(id -u):$(id -g) $HOME/.kube/config
# kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml
init 후 나온 토큰을 worker들에게 입력해준다.
# kubeadm join 192.168.56.104:6443 --token 30wnm4.gtujz6nuefecizs9 \
--discovery-token-ca-cert-hash sha256:dfbeaf6fe8d3da8ce0ae280d814d97b896e0f66eb7bad23b3af234e375c648e3
# pv-pvc-pod.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: task-pv-volume
labels:
type: local
spec:
storageClassName: manual
capacity:
storage: 10Mi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
hostPath:
path: "/mnt/data"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: task-pv-claim
spec:
storageClassName: manual
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Mi
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
💡 accessModes:
- ReadWriteOnce = 하나의 노드에서 해당 볼륨이 읽기-쓰기로 마운트 될 수 있다.
ReadWriteOnce 접근 모드에서도 파드가 동일 노드에서 구동되는 경우에는 복수의 파드에서 볼륨에 접근할 수 있다.
- ReadOnlyMany = 볼륨이 다수의 노드에서 읽기 전용으로 마운트 될 수 있다.
- ReadWriteMany = 볼륨이 다수의 노드에서 읽기-쓰기로 마운트 될 수 있다.
- ReadWriteOncePod = 볼륨이 단일 파드에서 읽기-쓰기로 마운트될 수 있다.
전체 클러스터에서 단 하나의 파드만 해당 PVC를 읽거나 쓸 수 있어야하는 경우 ReadWriteOncePod 접근 모드를 사용한다. 이 기능은 CSI 볼륨과 쿠버네티스 버전 1.22+ 에서만 지원된다.
💡 persistentVolumeReclaimPolicy:
- Retain(보존)
Retain 반환 정책은 리소스를 수동으로 반환할 수 있게 한다.
퍼시스턴트볼륨클레임이 삭제되면 퍼시스턴트볼륨은 여전히 존재하며 볼륨은 "릴리스 된" 것으로 간주된다.
그러나 이전 요청자의 데이터가 여전히 볼륨에 남아 있기 때문에 다른 요청에 대해서는 아직 사용할 수 없다.
관리자는 다음 단계에 따라 볼륨을 수동으로 반환할 수 있다.
- 퍼시스턴트볼륨을 삭제한다. PV가 삭제된 후에도 외부 인프라(예: AWS EBS, GCE PD, Azure Disk 또는 Cinder 볼륨)의 관련 스토리지 자산이 존재한다.
- 관련 스토리지 자산의 데이터를 수동으로 삭제한다.
- 연결된 스토리지 자산을 수동으로 삭제한다.
동일한 스토리지 자산을 재사용하려는 경우, 동일한 스토리지 자산 정의로 새 퍼시스턴트볼륨을 생성한다
- Delete(삭제)
Delete 반환 정책을 지원하는 볼륨 플러그인의 경우, 삭제는 쿠버네티스에서 퍼시스턴트볼륨 오브젝트와 외부 인프라(예: AWS EBS, GCE PD, Azure Disk 또는 Cinder 볼륨)의 관련 스토리지 자산을 모두 삭제한다.
동적으로 프로비저닝된 볼륨은 스토리지클래스의 반환 정책을 상속하며 기본값은 Delete이다. 관리자는 사용자의 기대에 따라 스토리지클래스를 구성해야 한다.
- Recycle(재활용)
경고: Recycle 반환 정책은 더 이상 사용하지 않는다.
대신 권장되는 방식은 동적 프로비저닝을 사용하는 것이다.
기본 볼륨 플러그인에서 지원하는 경우 Recycle 반환 정책은 볼륨에서 기본 스크럽(rm -rf /thevolume/*)을 수행하고 새 클레임에 다시 사용할 수 있도록 한다.
그러나 관리자는 레퍼런스에 설명된 대로 쿠버네티스 컨트롤러 관리자 커맨드라인 인자(command line arguments)를 사용하여 사용자 정의 재활용 파드 템플릿을 구성할 수 있다.
사용자 정의 재활용 파드 템플릿에는 아래 예와 같이 volumes 명세가 포함되어야 한다.
그러나 volumes 부분의 사용자 정의 재활용 파드 템플릿에 지정된 특정 경로는 재활용되는 볼륨의 특정 경로로 바뀐다.
# yum install -y nfs-utils.x86_64
# mkdir /nfs_shared
# echo '/nfs_shared 192.168.0.0/21(rw,sync,no_root_squash)' >> /etc/exports
# systemctl enable --now nfs
# vi nfs-pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv
spec:
capacity:
storage: 100Mi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
nfs:
server: 192.168.0.192
path: /nfs_shared
# kubectl apply -f nfs-pv.yaml
# kubectl get pv
# vi nfs-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs-pvc
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 10Mi
# kubectl apply -f nfs-pvc.yaml
# kubectl get pvc
# kubectl get pv
# vi nfs-pvc-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nfs-pvc-deploy
spec:
replicas: 4
selector:
matchLabels:
app: nfs-pvc-deploy
template:
metadata:
labels:
app: nfs-pvc-deploy
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- name: nfs-vol
mountPath: /usr/share/nginx/html
volumes:
- name: nfs-vol
persistentVolumeClaim:
claimName: nfs-pvc
# kubectl apply -f nfs-pvc-deploy.yaml
# kubectl get pod
# kubectl exec -it nfs-pvc-deploy-76bf944dd5-6j9gf -- /bin/bash
# kubectl expose deployment nfs-pvc-deploy --type=LoadBalancer --name=nfs-pvc-deploy-svc1 --port=80
1pod 2container
# vi multipod.yaml
apiVersion: v1
kind: Pod
metadata:
name: multipod
spec:
containers:
- name: nginx-container #1번째 컨테이너
image: 192.168.56.104:5000/nginx:latest
ports:
- containerPort: 80
- name: centos-container #2번째 컨테이너
image: 192.168.56.104:5000/centos:7:latest
command:
- sleep
- "10000"
# kubectl exec -it multipod -c nginx-container -- bash
apiVersion: v1
kind: Pod
metadata:
name: wordpress-pod
labels:
app: wordpress-pod
spec:
containers:
- name: mysql-container
image: mysql:5.7
env:
- name: MYSQL_ROOT_HOST
value: '%' # wpuser@%
- name: MYSQL_ROOT_PASSWORD
value: kosa0401
- name: MYSQL_DATABASE
value: wordpress
- name: MYSQL_USER
value: wpuser
- name: MYSQL_PASSWORD
value: wppass
ports:
- containerPort: 3306
- name: wordpress-container
image: wordpress
env:
- name: WORDPRESS_DB_HOST
value: wordpress-pod:3306
- name: WORDPRESS_DB_USER
value: wpuser
- name: WORDPRESS_DB_PASSWORD
value: wppass
- name: WORDPRESS_DB_NAME
value: wordpress
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: loadbalancer-service-deployment-wordpress
spec:
type: LoadBalancer
externalIPs:
- 192.168.56.104
selector:
app: wordpress-pod
ports:
- protocol: TCP
port: 80
[Persistent Volume에 Wordpress 배포하기] 괜찮은거 같음
# kubectl apply -f /root/_Book_k8sInfra/ch3/3.3.4/metallb.yaml
# kubectl get pods -n metallb-system -o wide
# vi metallb-l2config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
address-pools:
- name: nginx-ip-range
protocol: layer2
addresses:
- 192.168.56.200-192.168.56.250
# kubectl apply -f metallb-l2config.yaml
# kubectl describe configmaps -n metallb-system
# kubectl get pod -n metallb-system
# kubectl delete -f metallb-l2config.yaml
spec:
containers:
- name: demo
image: alpine
command: ["sleep", "3600"]
😈 k8s images 제한 시 😈
# kubectl create secret generic rldnjsdlsi --from-file=.dockerconfigjson=/root/.docker/config.json --type=kubernetes.io/dockerconfigjson # kubectl patch -n default serviceaccount/default -p '{"imagePullSecrets":[{"name": "rldnjsdlsi"}]}' # kubectl describe serviceaccount default -n default
- namespace를 따라가기 때문에 ns를 바꾸면 제한을 다시 풀어줘야한다..
💡 여러 deploy.yaml 합쳐서 한번에 실행하기
# kustomization.yaml resources: - mysql-deploy.svc.yaml - wordpress-deploy-svc.yaml
- 사용할 deploy.yaml 파일을 kustomization.yaml에 묶어 놓는다.
# kubectl apply -k ./
=> 로 실행 하면 2개의 deploy.yaml이 같이 실행된다.
apiVersion: v1
kind: ConfigMap
metadata:
name: config-wordpress
namespace: default
data:
MYSQL_ROOT_HOST: '%'
MYSQL_ROOT_PASSWORD: mode1752
MYSQL_DATABASE: wordpress
MYSQL_USER: wpuser
MYSQL_PASSWORD: wppass
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql-deploy
labels:
app: mysql-deploy
spec:
replicas: 1
selector:
matchLabels:
app: mysql-deploy
template:
metadata:
labels:
app: mysql-deploy
spec:
containers:
- name: mysql-container
image: mysql:5.7
envFrom:
- configMapRef:
name: config-wordpress
ports:
- containerPort: 3306
---
apiVersion: v1
kind: Service
metadata:
name: mysql-svc
spec:
type: ClusterIP
selector:
app: mysql-deploy
ports:
- protocol: TCP
port: 3306
targetPort: 3306
apiVersion: apps/v1
kind: Deployment
metadata:
name: wordpress-deploy
labels:
app: wordpress-deploy
spec:
replicas: 1
selector:
matchLabels:
app: wordpress-deploy
template:
metadata:
labels:
app: wordpress-deploy
spec:
containers:
- name: wordpress-container
image: wordpress
env:
- name: WORDPRESS_DB_HOST
value: mysql-svc:3306
- name: WORDPRESS_DB_USER
valueFrom:
configMapKeyRef:
name: config-wordpress
key: MYSQL_USER
- name: WORDPRESS_DB_PASSWORD
valueFrom:
configMapKeyRef:
name: config-wordpress
key: MYSQL_PASSWORD
- name: WORDPRESS_DB_NAME
valueFrom:
configMapKeyRef:
name: config-wordpress
key: MYSQL_DATABASE
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: wordpress-svc
spec:
type: LoadBalancer
# externalIPs:
# - 192.168.2.0
selector:
app: wordpress-deploy
ports:
- protocol: TCP
port: 80
targetPort: 80
# kubectl get namespaces
# kubectl config get-contexts kubernetes-admin@kubernetes
# kubectl config set-context kubernetes-admin@kubernetes --namespace=kube-system
# kubectl config get-contexts kubernetes-admin@kubernetes
# kubectl config set-context kubernetes-admin@kubernetes --namespace=default
# kubectl create namespace test-namespace
- 내가 만드는 내 namespace
# kubectl get namespace
# kubectl config set-context kubernetes-admin@kubernetes --namespace=test-namespace
- k8s 관리자를 통해 test-namespace를 default namespace로 지정
# kubectl config set-context kubernetes-admin@kubernetes --namespace=default
- 다시 k8s 관리자를 통해 default를 default namespace로 지정
# kubectl delete namespaces test-namespace
- namespaces를 다 쓰고 지우면 해당 ns안에 있는 내용이 싹 다 삭제된다.
그럼 현재 ns를 확인하는 방법은..?
# vi sample-resourcequota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: sample-resourcequota
namespace: default
spec:
hard:
count/pods: 5
# kubectl describe resourcequotas sample-resourcequota
# kubectl run pod new-nginx --image=nginx
apiVersion: v1
kind: ResourceQuota
metadata:
name: sample-resourcequota-usable
namespace: default
spec:
hard:
requests.memory: 2Gi
requests.storage: 5Gi
sample-storageclass.storageclass.storage.k8s.io/requests.storage: 5Gi
requests.ephemeral-storage: 5Gi
requests.nvidia.com/gpu: 2
limits.cpu: 4
limits.ephemeral-storage: 10Gi
limits.nvidia.com/gpu: 4
apiVersion: v1
kind: Pod
metadata:
name: sample-pod
spec:
containers:
- name: nginx-container
image: nginx:1.16
resources:
requests:
memory: "1Gi"
cpu: "50m"
limits:
memory: "6Gi"
cpu: "100m"
# kubectl describe node worker1
apiVersion: v1
kind: LimitRange
metadata:
name: sample-limitrange-container
namespace: default
spec:
limits: # 최대 2개 파드 생성, 1개 더하면 생성 안됨
- type: Container # 컨테이너에 대한
default: # 기본 최대 Limits, 정한 리소스가 부족하면 컨테이너가 생성되지 않는다.
memory: 512Mi
cpu: 500m
defaultRequest: # 직접 정하지 않은 경우 최소 용량, 최소 확보 용량
memory: 256Mi
cpu: 250m
max: # 직접 설정할 경우 값
memory: 1024Mi
cpu: 1000m
min:
memory: 128Mi
cpu: 125m
maxLimitRequestRatio: # Requests와 Limit의 차이 허용 비율 2배, 오버 커밋을 피할 수 있다.
memory: 2
cpu: 2
apiVersion: v1
kind: Pod
metadata:
name: sample-pod-overrequest
spec:
containers:
- name: nginx-container
image: nginx:1.16
resources:
requests:
cpu: 100m
limits:
cpu: 100m
# vi pod-schedule.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-schedule-metadata
labels:
app: pod-schedule-labels
spec:
containers:
- name: pod-schedule-containers
image: nginx
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: pod-schedule-service
spec:
type: NodePort
selector:
app: pod-schedule-labels
ports:
- protocol: TCP
port: 80
targetPort: 80
apiVersion: v1
kind: Pod
metadata:
name: pod-nodename-metadata
labels:
app: pod-nodename-labels
spec:
containers:
- name: pod-nodename-containers
image: nginx
ports:
- containerPort: 80
nodeName: worker2
---
apiVersion: v1
kind: Service
metadata:
name: pod-nodename-service
spec:
type: NodePort
selector:
app: pod-nodename-labels
ports:
- protocol: TCP
port: 80
targetPort: 80
# kubectl label nodes worker1 tier=dev
- worker1 node에 dev라는 label을 달아준다.
# kubectl get nodes --show-labels
- node들의 label까지 모두 출력한다.
# vi pod-nodeselector.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-nodeselector-metadata
labels:
app: pod-nodeselector-labels
spec:
containers:
- name: pod-nodeselector-containers
image: nginx
ports:
- containerPort: 80
nodeSelector:
tier: dev
---
apiVersion: v1
kind: Service
metadata:
name: pod-nodeselector-service
spec:
type: NodePort
selector:
app: pod-nodeselector-labels
ports:
- protocol: TCP
port: 80
targetPort: 80
# kubectl label nodes worker1 tier-
- 지정해줬던 label을 기본값으로 돌려놓는다.
# kubectl get nodes --show-labels
taint
자동 스케쥴을 못하게 만들어 (pod가 생성되지 않는다.) 수동으로만 설정하게 만든다.
toleration
taint되어 있는 node에 강제로 pod을 생성한다.
# kubectl taint node worker1 tier=dev:NoSchedule
# kubectl describe nodes worker1
# vi pod-taint.yaml