- 쿠버네티스를 사용하는 관점에서 파드와 디플로이먼트는 스펙(spec)과 상태(status)등의 값을 가지고 있다.
- 이런 값을 가지고 있는 파드와 디플로이먼트를 개별 속성을 포함해 부르는 단위를 오브젝트라 한다.
- k8s는 모든 기능을 오브젝트(객체)로 관리한다.
기본 오브젝트
pod
- k8s에서 최소 단위이며, 1개 이상으 컨테이너를 가지고 있어 여러 기능을 묶어 하나의 목적으로 사용 가능하다.
- 웹 서비스를 구현하는데 필요한 가장 최소 단위
- 독립적인 공간과 사용 가능한 IP를 가지고 있다.
네임스페이스
- k8s 클러스터에서 사용되는 리소스들을 구분해 관리하는 그룹이다.
- 3가지의 네임스페이스가 있다.
- 특별히 지정하지 않으면 default로 지정된다.
볼륨
- 파드가 생성될 때 파드에서 사용할 수 있는 디렉터리를 제공한다.
- 내부 저장소는 영속적이지 않지만 외부 저장소는 파드가 사라지더라도 데이터를 저장과 보존이 가능하다
서비스
- 외부에서 클러스터 내의 pod로 접속할 수 있는 방법
LB, nodeport, cluster ip
디플로이먼트
- 기존 오브젝트로만 k8s를 구성할 수 있지만, 한계가 있어 이를 효율적으로 작동하도록 기능을 조합,추가하여 구현한 것이다
- 일반적인 포드는 삭제가 자유로운 포드이며 이름의 경우도 임의의 hash 뒤에 붙이게 된다.
deployment : test-deploy replicaset : test-deploy-12345(2개의 pod를 유지하겟다) pod : test-deploy-12345-dawdwd test-deploy-12345-wdawnl - statefulset을 적용한다면 test-deploy-12345-1 test-deploy-12345-2
목적에 맞는 오브젝트
- 데몬셋 - 각 노드에 무조건 일괄적으로 하나씩 배포, 모니터링등에 활용하면 유용하다.
- 컨피그맵(configMap) - 시스템 환경변수, 일반적인 파일 등을 제공하기 위한 방법이다.(보안성은 없다)
- Secret - 컨피그맵과 거의 동일하지만 해당 데이터가 외부에 노출되지 않는다는 장점이 있어서, 주로 인증, key, susername/password, ssh 접속등과 같은 보안성을 요구하는 곳에서 활용한다.
- 가령, 특정 사설 저장소로 접속하기 위한 username, password,address를 secret으로 작성하여 yaml 파일에 적용할 경우 특정 저장소에서 파일을 다운로드할 때 유용하다.
파드 업데이트하기
cat nginx1.yml apiVersion: apps/v1 kind: Deployment metadata: name: test spec: replicas: 3 selector: matchLabels: color: blue template: metadata: labels: color: blue spec: containers: - name: test image: nginx
- pod 배포
kubectl apply -f nginx1.yml
- pod 정보 확인
kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES test-69454c947b-ggccm 1/1 Running 0 15s 10.64.0.7 gke-mytestcluster-default-pool-f9572c5c-fvhz <none> <none> test-69454c947b-nmlp2 1/1 Running 0 15s 10.64.1.4 gke-mytestcluster-default-pool-f9572c5c-fvj0 <none> <none> test-69454c947b-z6b75 1/1 Running 0 15s 10.64.2.6 gke-mytestcluster-default-pool-f9572c5c-ph7f <none> <none>
v1 - apply - kubectl get pod
v2 - apply - kubectl get pod
Rolling Update
- 새로 만든 컨테이너 수 만큼, 기존 컨테이너 삭제한다. 시간이 오래 걸리기 때문에 알맞는 상황에 사용해야한다.
- 예를 들어, 한 번에 삭제할 컨테이너 수를 지정하여, 해당 수만큼 컨테이너를 생성한다.
- 삭제 개수와 추가 생성 개수를 지정해서 사용할 수 있다
cat nginx1.yml apiVersion: apps/v1 kind: Deployment metadata: name: test spec: strategy: type: RollingUpdate rollingUpdate: maxSurge: 2 maxUnavailable: 2 replicas: 3 selector: matchLabels: color: blue template: metadata: labels: color: blue spec: containers: - name: test image: nginx
- RollingUpdate 를 적용하게 되면 기존 서비스의 중단이 없이, 새로운 포드의 생성을 미리 산정하고 계획할수 있게된다. 만약 서비스 중에 처리 속도가 늦어진다면 maxsurge, maxunavailable 을 조정하여 안정적으로 서비스를 유지시킬 수 있게된다.
2. Recreate
- 기존 Pod 를 모두 종료 ( terminate ) 시킨 다음, 새로운 Pod 로 전환
- type: Recreate -> 종료되는 중간에는 해당 애플리케이션으로의 외부 접속이 불가능해지는 문제가 발생한다.
cat nginx1.yml apiVersion: apps/v1 kind: Deployment metadata: name: test spec: strategy: type: Recreate replicas: 3 selector: matchLabels: color: blue template: metadata: labels: color: blue spec: containers: - name: test image: nginx
- 배포하기
kubectl apply -f nginx1.yml
- 이미지 변경 후 배포
kubectl get pod ; sed -i 's/image: httpd/image: ngix/' nginx1.yml ; kubectl apply -f nginx1.yml ; kubectl get pod
cluseter ip
- 두개의 포트가 있는 경우 각 포드 별로 별도의 IP주소를 사용한다.
- 이들은 서로간에 통신을 할 경우 각 포드가 서로 다른 노드에 있다고 가정한다면 이들을 마치 하나의 네트워크에 연결하기 위한 환경이 필요한데 이러한 클러스터 상에서 서로 다른 노드에 있는 포드들간 통신이 가능하도록 하기 위하여 cluster ip를 두게 된다.
NodePort
- 외부에서 클러스터 내부에 접속하기에 가장 쉬운 방법이다.
- 노드 포트 서비스를 설정하면 모든 워커 노드의 특정 포트( 30000 ~ 32768 )를 열고 여기로 오는 모든 요청을 노드포트 서비스로 전달하고 노드 포트 서비스는 해당 업무를 처리할 수 있는 파드에 여청을 전달한다.
- 라벨 지정
1. replicaset
- 어떤 포트의 라벨을 확인하고 지정된 개수를 유지할 것인가에 활용
2. service
- (노드포트에서) 노드의 포트로 접속된 트래픽에 대하여 누구(포드)에게 전달할 것인가 -> label
port 80-> nodeport 로 접속된 트래픽을 nodeport 서비스의 특정 포트(80/tcp)로 유입되면(2)
targetPort 80-> 최종적으로 목적지 포드의 80번포트로 전달하겠다(3)
nodePort 30000 -> 외부에서 가상머신의 어떤 포트로 접속하면?(1)
Port 를 3 가지 지정해야 한다nodePort : 외부에서 Node 에 접속할 Port port : Node 로 접속된 트래픽이 전달될 node Port 서비스의 특정 포트 targetPort : node Port 서비스의 특정 포트에 트래픽이 전달시 최종적으로 전달될 Pod 의 Port
cat nginx1.yml metadata: name: test spec: strategy: type: RollingUpdate rollingUpdate: maxSurge: 2 maxUnavailable: 2 replicas: 3 selector: matchLabels: color: blue template: metadata: labels: color: blue spec: containers: - name: test image: nginx --- # --- 를 사용하면 작업을 구분 apiVersion: v1 kind: Service metadata: name: test spec: selector: color: blue ports: - name: http protocol: TCP port: 80 targetport: 80 nodePort: 30000 type: NodePort
방화벽 규칙 생성 및 삭제
$ gcloud compute firewall-rules create permitnp --allow=tcp:30000 $ gcloud compute firewall-rules delete permitnp
스케일 조정
- 포드3 -> 포드1
kubectl scale --replicas 1 deploy test
External Traffic Policy: Cluster (기본값)
- 해당 노드에 포드가 없다고 하더라도 클러스터를 통해 다른 노드에 있는 포드로 트래픽이 전송된다. 이때 hop 을 바꾸기 때문에 결국 라우팅이 발생한다.
- Local 로 변경하면 해당 노드에 있는 포드로만 접속하게 되고 만약 포드가 없다면 서비스를 받을 수 없게 된다.
- 하지만 불필요한 라우팅은 없기 때문에 DC 에 부담을 줄일 수 있게된다.
apiVersion: apps/v1 kind: Deployment metadata: name: test spec: strategy: type: RollingUpdate rollingUpdate: maxSurge: 2 maxUnavailable: 2 replicas: 3 selector: matchLabels: color: blue template: metadata: labels: color: blue spec: containers: - name: test image: nginx --- apiVersion: v1 kind: Service metadata: name: test spec: selector: color: blue externalTrafficPolicy: Local ports: - name: http protocol: TCP port: 80 targetPort: 80 nodePort: 30000 type: NodePort
- 배포하기
kubectl apply -f nginx1.yaml
kubectl get pod,svc NAME READY STATUS RESTARTS AGE pod/test-69454c947b-258lg 1/1 Running 0 4m44s pod/test-69454c947b-6tq7q 1/1 Running 0 149m pod/test-69454c947b-dg2vk 1/1 Running 0 4m44s
kubectl describe svc test : : External Traffic Policy: Local
- 스케일 조정
kubectl scale --replicas 1 deploy test
kubectl get pod NAME READY STATUS RESTARTS AGE test-69454c947b-6tq7q 1/1 Running 0 152m
- 이후 3 페이지로 접속해 보면 1곳에서만 정상적으로 페이지가 보이고 나머지 2곳은 페이지로 접속이 되지 않는다.
rules: - host: www.test.com 1) www.test.com 2) www.test.com/ip , 3) www.test.com/y... http: paths - path backend: servicename: hname-svc-default -> 서비스를 제공하는 포트의 어떤 경로로 접속되도록 할 것인가? : / -> 포드의 기본 웹 디렉토리로 전달하겠다
- 포드에서는 아래와 같이 구성해야 한다.
/var/www/html/index.html - path: /ip - path: /your-directory
- ingress는 svc와 연결하여 사용해야 한다.
LB | NodePort ------> ingress-controller
-ingress.yamlapiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: example spec: rules: - host: www.test.pri http: paths: - path: / pathType: Prefix backend: service: name: example port: number: 80
- 인그레스 컨트롤러 배포
kubectl apply -f \ https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.1.2/deploy/static/provider/cloud/deploy.yaml
- 서비스 제공을 위한 포드 배포
kubectl run example --image=nginx
- vm의 랜덤포트(30000~ ) -> nodeport:80 -> pod:80
kubectl expose pod example --port=80 --name example --type=NodePort
- 포트 확인
kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE example NodePort 10.12.4.16 <none> 80:30594/TCP 84s www.test.pri:30594 ---> nodeport:80 -------> pod/example:80 /var/www/html
- 기존 ingress.yaml 에 아래내용 추가
metadata: name: example annotations: nginx.ingress.kubernetes.io/rewrite-target: /$1 kubernetes.io/ingress.class: "nginx" spec:
- 인그레스 배포
kubectl apply -f ingress.yaml
- 노트포트접속을 위하여 가상머신의 포트를 오픈하기위한 방화벽 설정
gcloud compute firewall-rules create permitingress --allow=tcp:3XXXX
- 최종접속
curl -L http:www.test.pri:3XXXX
- [최종결과]
curl -s http://yang.test.pri:31597 | head -5 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style>
잘보고 갑니다