[클라우드 네이티브] Pod 자세히 보기

1. Pod의 기본 개념

  • Pod는 Kubernetes에서 가장 작은 리소스 관리 구성 요소이며, 컨테이너화된 애플리케이션 실행을 최소화하는 리소스 개체이기도 합니다. Pod는 클러스터에서 실행되는 프로세스를 나타냅니다. Kubernetes의 다른 구성요소 대부분은 Pod를 중심으로 회전하여 Pod 기능을 지원하고 확장합니다. 예를 들어 StatefulSet 및 배포와 같은 컨트롤러 객체는 Pod 실행을 관리하는 데 사용되고, Service 및 Ingress 객체는 Pod 애플리케이션을 노출하고 Pod에 서비스를 제공하는 데 사용됩니다. 저장된 PertantVolume은 리소스 객체 등을 저장합니다.

1.1//Kubrenes 클러스터에서는 Pod를 다음 두 가지 방법으로 사용할 수 있습니다.

●컨테이너는 Pod에서 실행됩니다. "각 포드에 하나의 컨테이너" 모델이 가장 일반적인 사용법입니다. 이 사용법에서는 포드를 단일 컨테이너의 캡슐화로 생각할 수 있으며 kuberentes는 컨테이너를 직접 관리하는 대신 포드를 관리합니다.

●Pod에서 여러 컨테이너를 동시에 실행합니다. 또한 포드는 서로 긴밀하게 연결되고 협력하며 리소스를 공유해야 하는 여러 컨테이너를 캡슐화할 수도 있습니다. 동일한 포드에 있는 이러한 컨테이너는 서로 협력하여 파일을 공유하는 하나의 컨테이너와 이러한 파일을 업데이트하는 다른 "사이드카" 컨테이너와 같은 서비스 단위를 형성할 수 있습니다. Pod는 이러한 컨테이너의 스토리지 리소스를 엔터티로 관리합니다.

Pod 아래의 컨테이너는 동일한 노드에서 실행되어야 합니다. 최신 컨테이너 기술에서는 컨테이너가 하나의 프로세스만 실행할 것을 권장합니다. 컨테이너의 PID 네임스페이스에 있는 프로세스 번호는 1이며, 이는 신호를 직접 수신하고 처리할 수 있습니다. 프로세스가 종료되면 컨테이너 수명 주기가 종료됩니다. 컨테이너에서 여러 프로세스를 실행하려면 트리 구조에서 여러 프로세스의 수명주기 관리를 완료하기 위해 Linux 운영체제의 init 프로세스와 유사한 관리 및 제어 프로세스가 필요합니다. 각 컨테이너에서 실행 중인 프로세스는 네트워크 통신을 직접 완료할 수 없습니다. 이는 컨테이너 간의 격리 메커니즘 때문입니다. k8s의 Pod 리소스 추상화는 이 문제를 해결합니다. Pod 개체는 NET, MNT, UTS 및 IPC 네임스페이스를 공유하는 컨테이너 모음입니다. 이므로 동일한 도메인 이름, 호스트 이름 및 네트워크 인터페이스를 가지며 IPC를 통해 직접 통신할 수 있습니다.

Pod 리소스의 기본 기본 컨테이너 일시 중지는 각 컨테이너에 대한 네트워크 네임스페이스 및 기타 공유 메커니즘을 제공합니다. 기본 컨테이너(상위 컨테이너라고도 함) 일시 중지는 Pod 컨테이너 간의 공유 작업을 관리하는 것입니다. 이 상위 컨테이너는 어떻게 해야 하는지 정확히 알 수 있어야 합니다. 실행 환경을 공유하는 컨테이너를 만들고 이러한 컨테이너의 수명 주기를 관리합니다. 이 상위 컨테이너의 아이디어를 구현하기 위해 Kubernetes에서는 일시 중지 컨테이너를 Pod에 있는 모든 컨테이너의 상위 컨테이너로 사용합니다. 이 일시 중지 컨테이너에는 두 가지 핵심 기능이 있는데, 그 중 하나는 전체 Pod의 Linux 네임스페이스에 대한 기반을 제공한다는 것입니다. 둘째, 각 Pod에서 PID 1(init 프로세스)을 사용하는 프로세스 역할을 하고 좀비 프로세스를 재활용하는 PID 네임스페이스를 활성화합니다.

1.2pause 컨테이너를 사용하면 Pod의 모든 컨테이너가 네트워크와 스토리지라는 두 가지 리소스를 공유할 수 있습니다.

●네트워크:

각 포드에는 고유한 IP 주소가 할당됩니다. IP 주소 및 포트를 포함하여 포드의 모든 컨테이너는 네트워크 공간을 공유합니다. Pod 내부의 컨테이너는 localhost를 사용하여 서로 통신할 수 있습니다. 포드의 컨테이너가 외부 세계와 통신할 때 공유 네트워크 리소스를 할당해야 합니다(예: 호스트의 포트 매핑 사용).

●저장공간 :

포드는 여러 공유 볼륨을 지정할 수 있습니다. Pod의 모든 컨테이너는 공유 볼륨에 액세스할 수 있습니다. 컨테이너가 다시 시작된 후 파일 손실을 방지하기 위해 볼륨을 사용하여 포드의 스토리지 리소스를 유지할 수도 있습니다.

1.3 쿠버네티스의 일시 중지 컨테이너는 주로 각 컨테이너에 대해 다음 기능을 제공합니다.

●Pod에서 Linux 네임스페이스(예: 네트워크 명령 공간)를 공유하기 위한 기반 역할을 하며,
●PID 네임스페이스를 활성화하고 init 프로세스를 시작합니다.

1.4이러한 Pod 개념과 특별한 구성 구조를 설계하는 Kubernetes의 목적은 무엇입니까? ? ? ? ?

●이유 1: 컨테이너 그룹을 하나의 단위로 취급할 경우 단순히 컨테이너 전체에 대해 효과적으로 판단하고 행동하기가 어렵습니다. 예를 들어 컨테이너가 죽으면 컨테이너 전체가 다운된 것으로 간주됩니까? 그런 다음 비즈니스와 관련이 없는 Pause 컨테이너를 Pod의 기본 컨테이너로 도입하고 그 상태가 전체 컨테이너 그룹의 상태를 나타내므로 이 문제를 해결할 수 있습니다.

●이유 2: Pod에 있는 여러 애플리케이션 컨테이너는 Pause 컨테이너의 IP와 Pause 컨테이너에 마운트된 볼륨을 공유하므로 애플리케이션 컨테이너 간의 통신 문제가 단순화되고 컨테이너 간 파일 공유 문제도 해결됩니다.

1.5 포드는 일반적으로 다음 카테고리로 나뉩니다.

●자율 포드

이러한 종류의 Pod 자체는 자체 복구가 불가능합니다. Pod가 생성되면(직접 생성했든 다른 컨트롤러에서 생성했든) Kuberentes가 클러스터 노드에 예약합니다. 포드는 포드의 프로세스가 종료되거나, 삭제되거나, 리소스 부족으로 인해 제거되거나, 노드가 실패할 때까지 해당 노드에 유지됩니다. 포드는 스스로 치유되지 않습니다. Pod를 실행하는 노드가 실패하거나 스케줄러 자체가 실패하면 Pod가 삭제됩니다. 마찬가지로, Pod가 위치한 노드에 리소스가 부족하거나 Pod가 유지 관리 상태인 경우에도 Pod가 제거됩니다.

●컨트롤러가 관리하는 포드

Kubernetes는 컨트롤러라는 상위 수준 추상화 계층을 사용하여 포드 인스턴스를 관리합니다. 컨트롤러는 여러 포드를 생성하고 관리하여 복사 관리, 롤링 업그레이드, 클러스터 수준 자가 복구 기능을 제공할 수 있습니다. 예를 들어 노드에 장애가 발생하면 컨트롤러는 해당 노드의 포드를 다른 정상 노드에 자동으로 예약할 수 있습니다. 포드를 직접 사용할 수도 있지만 컨트롤러는 일반적으로 Kubernetes에서 포드를 관리하는 데 사용됩니다.

●정적 포드

정적 포드는 마스터 노드의 apiserver를 통하지 않고 특정 노드의 kubelet 프로세스에 의해 직접 관리됩니다. 이는 컨트롤러 배포 또는 DaemonSet과 연결될 수 없으며 kubelet 프로세스 자체에 의해 모니터링됩니다. 포드가 충돌하면 포드가 다시 시작되고 kubelet은 이에 대한 상태 확인을 수행할 수 없습니다. 정적 Pod는 항상 특정 kubelet에 바인딩되며 항상 동일한 노드에서 실행됩니다. Kubelet은 Kubernetes apiserver의 각 정적 Pod에 대해 자동으로 미러 Pod(Mirror Pod)를 생성하므로 apiserver에서 Pod를 쿼리할 수 있지만 apiserver를 통해 제어할 수는 없습니다(예: 삭제할 수 없음).

kubelet 구성 파일 보기

/var/lib/kubelet/config.yaml
cat /var/lib/kubelet/config.yaml | grep staticPodPath
staticPodPath: /etc/kubernetes/manifests

다음 명령을 사용하여 kubelet에 해당하는 시작 구성 파일을 찾고, 노드 node의 kubelet 구성 파일을 수정하고, 정적 Pod --pod-manifest-path 매개변수의 환경 변수 구성을 추가할 수도 있습니다.

systemctl status kubelet
/usr/lib/systemd/system/kubelet.service.d
     └─10-kubeadm.conf

vim /usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf
Environment="KUBELET_SYSTEM_PODS_ARGS=--pod-manifest-path=/etc/kubernetes/manifests --allowprivileged=true"

systemctl daemon-reload
systemctl restart kubelet

정적 Pod 파일의 관리 디렉터리에 Pod의 Json 또는 Yaml 파일을 준비합니다.

vim /etc/kubernetes/manifests/static-web.yaml
apiVersion: v1
kind: Pod
metadata:
  name: static-web
  labels:
    app: static
spec:
  containers:
    - name: web
      image: nginx
      ports:
        - name: web
          containerPort: 80
  • 실행 중인 kubelet은 구성된 디렉터리에서 파일 변경 사항을 주기적으로 검색하고, 이 디렉터리에 파일이 나타나거나 사라질 때 Pod를 생성하거나 삭제합니다.
  • 해당 Pod는 마스터 노드에서도 볼 수 있는데, kubectl delete pod static-web-node01 명령을 실행하여 Pod를 삭제하면 삭제할 수 없는 것을 확인할 수 있습니다.

1.6포드 컨테이너 분류:

1. 인프라 컨테이너

  • 전체 Pod 네트워크 및 저장 공간 유지
  • 노드의 노드 작업
  • Pod를 시작하면 k8s는 자동으로 기본 컨테이너를 시작합니다.
cat /opt/kubernetes/cfg/kubelet
......
--pod-infra-container-image=registry.cn-hangzhou.aliyuncs.com/google-containers/pause-amd64:3.0"
  • Pod가 생성될 때마다 생성되며, 실행 중인 각 Pod에는 자동으로 실행되는 Pause-AMD64 기본 컨테이너가 있으며 이는 사용자에게 투명합니다.
docker ps -a
registry.cn-hangzhou.aliyuncs.com/google-containers/pause-amd64:3.0   "/pause"

2. 컨테이너 초기화(initcontainers)

  • init 컨테이너는 애플리케이션 컨테이너가 시작되기 전에 완료될 때까지 실행되어야 하며 애플리케이션 컨테이너는 병렬로 실행되므로 init 컨테이너는 애플리케이션 컨테이너의 시작을 차단하거나 지연하는 간단한 방법을 제공할 수 있습니다.
    Init 컨테이너는 다음 두 가지 점을 제외하고 일반 컨테이너와 매우 유사합니다.

●Init 컨테이너는 성공적으로 완료될 때까지 항상 실행됩니다.

●각 Init 컨테이너는 다음 Init 컨테이너가 시작되기 전에 시작과 종료를 성공적으로 완료해야 합니다.
Pod의 Init 컨테이너가 실패하면 k8s는 Init 컨테이너가 성공할 때까지 계속해서 Pod를 다시 시작합니다. 하지만 해당 포드의 다시 시작 정책(restartPolicy)이 Never인 경우에는 다시 시작되지 않습니다.

Init의 컨테이너 역할

  • init 컨테이너에는 애플리케이션 컨테이너와 별도의 이미지가 있으므로 시작 관련 코드에는 다음과 같은 장점이 있습니다.

●Init 컨테이너에는 설치 중에 애플리케이션 컨테이너에 없는 일부 유틸리티나 개인화 코드가 포함될 수 있습니다. 예를 들어 설치 프로세스 중에 sed, awk, python 또는 dig와 같은 도구를 사용하기 위해 이미지에서 새 이미지를 생성할 필요가 없습니다.

●Init 컨테이너는 이러한 도구를 안전하게 실행하여 이러한 도구가 애플리케이션 이미지의 보안을 저하시키는 것을 방지할 수 있습니다.

●애플리케이션 이미지 생성자와 배포자는 별도의 애플리케이션 이미지를 공동으로 구축할 필요 없이 독립적으로 작업할 수 있습니다.

●Init 컨테이너는 Pod 내의 애플리케이션 컨테이너와 다른 파일 시스템 보기로 실행될 수 있습니다. 따라서 Init 컨테이너는 Secrets에 액세스할 수 있지만 애플리케이션 컨테이너는 액세스할 수 없습니다.


●Init 컨테이너는 응용 프로그램 컨테이너가 시작되기 전에 실행이 완료되어야 하기 때문에 Init 컨테이너는 일련의 전제 조건이 충족될 때까지 응용 프로그램 컨테이너의 시작을 차단하거나 지연하는 메커니즘을 제공합니다 . 전제 조건이 충족되면 Pod의 모든 애플리케이션 컨테이너가 병렬로 시작됩니다.

3. 도포용기(메인컨테이너)

  • 병렬 시작

공식 웹사이트 예:

https://kubernetes.io/docs/concepts/workloads/pods/init-containers/

piVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
spec:
  containers:
  - name: myapp-container
    image: busybox:1.28
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']
  initContainers:
  - name: init-myservice
    image: busybox:1.28
    command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;']
  - name: init-mydb
    image: busybox:1.28
    command: ['sh', '-c', 'until nslookup mydb; do echo waiting for mydb; sleep 2; done;']
  • 이 예시에서는 2개의 Init 컨테이너가 있는 간단한 Pod를 정의합니다. 첫 번째는 myservice가 시작될 때까지 기다리고, 두 번째는 mydb가 시작될 때까지 기다립니다. 두 Init 컨테이너가 모두 시작되면 Pod는 사양의 애플리케이션 컨테이너를 시작합니다.

케이

ubectl describe pod myapp-pod

kubectl logs myapp-pod -c init-myservice

vim myservice.yaml
apiVersion: v1
kind: Service
metadata:
  name: myservice
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9376
	
kubectl create -f myservice.yaml

kubectl get svc

kubectl get pods -n kube-system

kubectl get pods

vim mydb.yaml
apiVersion: v1
kind: Service
metadata:
  name: mydb
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9377
	
kubectl create -f mydb.yaml

kubectl get pods

특별 참고 사항

●Pod 시작 프로세스 중에 네트워크 및 데이터 볼륨이 초기화된 후 Init 컨테이너가 순차적으로 시작됩니다. 다음 컨테이너를 시작하려면 각 컨테이너를 성공적으로 종료해야 합니다.
●런타임 또는 실패 종료로 인해 컨테이너가 시작되지 않으면 포드의 restartPolicy에 지정된 정책에 따라 다시 시도합니다. 그러나 Pod의 restartPolicy가 Always로 설정된 경우 Init 컨테이너가 실패하면 RestartPolicy 정책이 사용됩니다.
●모든 Init 컨테이너가 성공할 때까지 포드는 준비 상태가 되지 않습니다. Init 컨테이너의 포트는 서비스에 집계되지 않습니다. 초기화 중인 포드는 Pending 상태이지만 초기화 중 상태는 true로 설정되어야 합니다.
●Pod가 다시 시작되면 모든 Init 컨테이너를 다시 실행해야 합니다.
●Init 컨테이너 사양에 대한 수정은 컨테이너 이미지 필드로 제한되며 다른 필드에 대한 수정 사항은 적용되지 않습니다. Init 컨테이너의 이미지 필드를 변경하는 것은 포드를 다시 시작하는 것과 같습니다.
●Init 컨테이너에는 응용 컨테이너의 모든 필드가 포함되어 있습니다. readinessProbe는 제외됩니다. 왜냐하면 Init 컨테이너는 완료 이외의 준비 상태 이외의 다른 상태를 정의할 수 없기 때문입니다. 이는 유효성 검사 프로세스 중에 시행됩니다.
●Pod에 있는 각 앱 및 Init 컨테이너의 이름은 고유해야 하며, 다른 컨테이너와 동일한 이름을 공유하면 확인 중에 오류가 발생합니다.

1.7 이미지 풀 정책(imagePullPolicy)

  • Pod의 핵심은 컨테이너를 실행하는 것입니다. Docker와 같은 컨테이너 엔진을 지정해야 합니다. 컨테이너를 시작할 때 이미지를 가져와야 합니다. k8s의 이미지 가져오기 전략은 사용자가 지정할 수 있습니다.
    • 1. IfNotPresent: 이미지가 이미 존재하는 경우 kubelet은 더 이상 이미지를 가져오지 않으며 로컬에서 누락된 경우에만 웨어하우스에서 이미지를 가져옵니다. 기본 이미지 가져오기 전략
    • 2. 항상: 포드가 생성될 때마다 이미지를 다시 가져옵니다.
    • 3. 안 함: 포드가 이 이미지를 적극적으로 가져오지 않고 로컬 이미지만 사용합니다.
      참고: ":latest" 레이블이 있는 이미지 파일의 경우 기본 이미지 획득 정책은 "Always"이고, 다른 레이블이 있는 이미지의 경우 기본 정책은 "IfNotPresent"입니다.

공식 예:

https://kubernetes.io/docs/concepts/containers/images

에게

bectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: private-image-test-1
spec:
  containers:
    - name: uses-private-image
      image: $PRIVATE_IMAGE_NAME
      imagePullPolicy: Always
      command: [ "echo", "SUCCESS" ]
EOF


//master01 上操作
kubectl edit deployment/nginx-deployment
......
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:1.15.4
        imagePullPolicy: IfNotPresent							#镜像拉取策略为 IfNotPresent
        name: nginx
        ports:
        - containerPort: 80
          protocol: TCP
        resources: {
    
    }
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      dnsPolicy: ClusterFirst
      restartPolicy: Always										#Pod的重启策略为 Always,默认值
      schedulerName: default-scheduler
      securityContext: {
    
    }
      terminationGracePeriodSeconds: 30
......

//테스트케이스 생성

mkdir /opt/demo
cd /opt/demo

vim pod1.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-test1
spec:
  containers:
    - name: nginx
      image: nginx
      imagePullPolicy: Always
      command: [ "echo", "SUCCESS" ]


kubectl create -f pod1.yaml

kubectl get pods -o wide
pod-test1                         0/1     CrashLoopBackOff   4          3m33s

//현재 Pod 상태가 비정상입니다. 이유는 echo 프로세스가 실행 후 종료되고, 컨테이너 수명 주기도 끝나기 때문입니다.

kubectl describe pod pod-test1
......
Events:
  Type     Reason     Age                 From                    Message
  ----     ------     ----                ----                    -------
  Normal   Scheduled  2m10s               default-scheduler       Successfully assigned default/pod-test1 to 192.168.80.11
  Normal   Pulled     46s (x4 over 119s)  kubelet, 192.168.80.11  Successfully pulled image "nginx"
  Normal   Created    46s (x4 over 119s)  kubelet, 192.168.80.11  Created container
  Normal   Started    46s (x4 over 119s)  kubelet, 192.168.80.11  Started container
  Warning  BackOff    19s (x7 over 107s)  kubelet, 192.168.80.11  Back-off restarting failed container
  Normal   Pulling    5s (x5 over 2m8s)   kubelet, 192.168.80.11  pulling image "nginx"
//可以发现 Pod 中的容器在生命周期结束后,由于 Pod 的重启策略为 Always,容器再次重启了,并且又重新开始拉取镜像

//修改 pod1.yaml 文件
cd /opt/demo
vim pod1.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-test1
spec:
  containers:
    - name: nginx
      image: nginx:1.14							#修改 nginx 镜像版本
      imagePullPolicy: Always
      #command: [ "echo", "SUCCESS" ]			#删除

//删除原有的资源
kubectl delete -f pod1.yaml 

//更新资源
kubectl apply -f pod1.yaml 

//查看 Pod 状态
kubectl get pods -o wide
NAME                              READY   STATUS    RESTARTS   AGE   IP            NODE            NOMINATED NODE
pod-test1                         1/1     Running   0          33s   172.17.36.4   192.168.80.11   <none>

//在任意 node 节点上使用 curl 查看头部信息
curl -I http://172.17.36.4
HTTP/1.1 200 OK
Server: nginx/1.14.2
......

1.8 하버 배포 및 프라이빗 프로젝트 생성

//Docker 하버 노드(192.168.80.30)에서 작업합니다.

systemctl stop firewalld.service
systemctl disable firewalld.service
setenforce 0

yum install -y yum-utils device-mapper-persistent-data lvm2 
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo 
yum install -y docker-ce
systemctl start docker.service
systemctl enable docker.service
docker version
//上传 docker-compose 和 harbor-offline-installer-v1.2.2.tgz 到 /opt 目录中
cd /opt
chmod +x docker-compose
mv docker-compose /usr/local/bin/

//部署 Harbor 服务
tar zxvf harbor-offline-installer-v1.2.2.tgz -C /usr/local/
vim /usr/local/harbor/harbor.cfg
--5行--修改,设置为Harbor服务器的IP地址或者域名
hostname = 192.168.80.30

cd /usr/local/harbor/
./install.sh

Harbor에서 새 프로젝트 만들기

(1) 브라우저 접속: http://192.168.80.10 Harbor WEB UI 인터페이스에 로그인합니다. 기본 관리자 사용자 이름과 비밀번호는 admin/Harbor12345입니다.
(2) 인터페이스에 로그인하기 위한 사용자 이름과 비밀번호를 입력한 후 다음을 수행할 수 있습니다. 새 프로젝트를 만듭니다. "+ 프로젝트" 버튼을 클릭합니다.
(3) 프로젝트 이름을 "kgc-project"로 입력하고 "확인" 버튼을 클릭하여 새 프로젝트를 생성합니다.

//각 노드의 개인 창고에 대한 연결을 구성합니다(각 줄 뒤의 쉼표에 유의하세요).

cat > /etc/docker/daemon.json <<EOF
{
  "registry-mirrors": ["https://6ijb8ubo.mirror.aliyuncs.com"],
  "insecure-registries":["192.168.80.30"]
}
EOF

systemctl daemon-reload
systemctl restart docker

//在每个 node 节点登录 harbor 私有仓库
docker login -u admin -p harbor12345 http://192.168.80.30

//在一个 node 节点下载 Tomcat 镜像进行推送
docker pull tomcat:8.0.52
docker images

docker tag tomcat:8.0.52 192.168.80.30/kgc-project/tomcat:v1
docker images

docker push 192.168.80.30/kgc-project/tomcat:v1


//查看登陆凭据
cat /root/.docker/config.json | base64 -w 0			#base64 -w 0:进行 base64 加密并禁止自动换行
ewoJImF1dGhzIjogewoJCSIxOTIuMTY4LjE5NS44MCI6IHsKCQkJImF1dGgiOiAiWVdSdGFXNDZTR0Z5WW05eU1USXpORFU9IgoJCX0KCX0sCgkiSHR0cEhlYWRlcnMiOiB7CgkJIlVzZXItQWdlbnQiOiAiRG9ja2VyLUNsaWVudC8xOS4wMy41IChsaW51eCkiCgl9Cn0=

추천

출처blog.csdn.net/wang_dian1/article/details/132191369