설규환 강사님

kyuhwan2015@gmail.com

 

레이블

- 레이블은 개체의 식별에 사용

- 컨트롤러, 서비스 등에서 selector를 사용하여 대상을 지정함

- 기타 대상을 특정할 경우 -l 옵션과 selector를 사용하여 대상 지정

 ex) kubectl get pod -l app=test

 

특수한 접두사가 붙은 레이블

- 사용자가 개체를 식별하기 위하여 붙인 레이블이 아닌, 쿠버네티스 클러스터에서 개체를 식별하기 위하여 부여한 레이블

- 일반적으로 사용자가 생성한 기본 리소스(파드, 컨트롤러, 서비스 등) 에는 존재하지 않음

 

$ kubectl get svc --namespace kube-system kube-dns -o yaml | less

...

  labels:

    k8s-app: kube-dns

    kubernetes.io/cluster-service: "true"

    kubernetes.io/name: KubeDNS

...

 

실습

pod-template-hash라는 값이 무작위로 생기고, 이 값이 nginx-label01 뒤에 붙어.

왜냐하면 pod은 계속 생겼다 지워졌다 하니까 랜덤한 값이 뒤에 붙어야되잖아.

 

 

 

교재 실습(242P) - 각자 다른 레이블 정보를 가지는 파드에 index.html 파일 복사

 

$ cat > index1.html
Hello Development Beta
$ cat > index2.html
Hello Production Beta
$ cat > index3.html
Hello Development Stable
$ cat > index4.html
Hello Production Stable
$ kubectl cp index1.html nginx-label01-58f576c6f4-vsr9k:/usr/share/nginx/html/index.html
$ kubectl cp index2.html nginx-label02-657ccdb46-9958x:/usr/share/nginx/html/index.html
$ kubectl cp index3.html nginx-label03-686d484df7-r9tmh:/usr/share/nginx/html/index.html
$ kubectl cp index4.html nginx-label04-6ff7b6c8bf-vlgll:/usr/share/nginx/html/index.html

 각각 다르게 로드밸런싱 되는거 보여주려구 한거임

 

 

레이블 직접 수정 방법 (현재 리소스에 그대로 변경)

1) kubectl edit <리소스종류> <리소스 이름>

 vi편집기를 사용하여 수정

 

2) kubectl label 명령을 사용하여 수정하는 방식

- kubectl label <리소스 종류> <리소스 이름> <레이블 키>=[값]        // 새로운 레이블 생성

- kubectl label <리소스 종류> <리소스 이름> <레이블 키>=[값] --overwrite  // 기존 레이블 정보 수정

- kubectl label <리소스 종류> <리소스 이름> <레이블 키>=               // 기존 레이블 키 유지 및 값 삭제

- kubectl label <리소스 종류> <리소스 이름> <레이블 키>-               // 기존 레이블 삭제

 

kubectl get ep 하면 endpoint가 나와.

여기서 endpoint는 뭐냐하면, pod의 ip야.

서비스가 selector에서 label 이용해서 pod을 연결하잖아.

그렇게 연결된 pod의 ip를 보여주는가봄.

 

 

참고)

nginx-label01 : deployment 이름

58f576c6f4 : replicasets 이름

ncvvv : pod 이름

 

질문1)

답변)

아니다. 그냥 수정만 하는거다. 수정한다고 해서 pod가 삭제되고 이런건 아니다.

그 위에 있는 값만 수정하는거라는데..? <- 이건 확인 필요하겠다.

 

질문2)

답변)

edit을 지양하고 apply를 사용하는 것이 옳다.

왜냐하면, edit으로 수정을 해버리면 기간이 오래될 경우 내가 이전에 어떤 수정을 가했는지

잊어버릴 수도 있고, 데이터 형태로 남지 않기 때문에 형상 관리에 좋지 않다.

필요에 따라서 할 수는 있다. (가능은 하다) 하지만 운영 관점에서 apply가 좋다. 

 

 

애너테이션(Annotation) -> 특정 용도가 없어. (레이블은 식별하기 위한 용도가 있짜나. 이건 그냥 참고의 용도!!!)

- 레이블과 유사한 구조: 키/값

- 레이블과 달리 개체 식별에 사용되지 않음

- 특수한 경우, 일부 설정값을 저장하기 위하여 사용

- 디플로이먼트 CHANGE-CAUSE

- 인그레스 rewrite-target

- 볼륨 default-class

- 특수한 경우를 제외하고는 어떠한 용도로도 사용 가능

- 주로 개체와 관련된 기타 정보 저장 시 사용: 개체 생성시 사용하는 YAML 파일에도 주석을 사용하여 개체와 관련된 정보를 넣을 수 있으나, YAML 파일의 주석 내용은 리소스에는 반영되지 않으므로, 리소스 자체에서 확인하여야 할 정보는 애너테이션을 사용하여 저장

 

특수한 경우 : 업데이트 했을 때, 어떤 업데이트를 했는지 기록할 때 annotation에 기록

이 작업은 어떤 작업을 하기 위해서 했다! 뭐 이런거 써주는거지.

특수한 경우가 아닐 경우에는, 해당 오브젝트 담당자 핸드폰 번호 이런거 적어놔도 되는거임.  

 

 

업데이트 전략 (배포 전략)

 

재-생성 (Re-creation)

- 현재 버전 어플리케이션을 구동하는 인스턴스를 전체 중지 후 신규 어플리케이션 배포

- 동시 운영을 고려할 필요가 없어 관리 용이

- 업데이트 시 중단 발생 (점검중)

 

롤링업데이트 (deployment의 기본 배포 방법)

- 전체 어플리케이션을 구동하고 있는 인스턴스 중 일부를 순차적으로 업데이트

- 무중단 업데이트

 

블루/그린 (예전 어플과 신규 어플이 동시에 운영되면 문제가 될 수 있을 때. 누구는 구 어플/누구는 신 어플 접속하면..)

- 현재 어플리케이션을 구동하고 있는 인스턴스와 같은 규모의 업데이트된 인스턴스 준비

- 준비가 완료된 후 트래픽을 기존 인스턴스에서 신규 인스턴스로 전환

- 무중단 업데이트

- 기존 인스턴스를 유지할 경우 즉시 롤백 가능

- 비용 문제

 

카나리 (Canary)

- 테스트 전략

- 롤링 업데이트와 같은 방식이나, 순차적으로 업데이트를 즉시 수행하지 않음

- 신규 어플리케이션의 이상 여부를 확인하기 위한 카나리 인스턴스 배포

- 카나리 인스턴스에 이상이 없을 경우 신규 버전으로 변경

- 카나리 인스턴스에 이상이 발생할 경우 카나리 인스턴스 배포 중지

 

기타 배포/테스트 전략

A/B 테스트 - 서로 다른 버전의 어플리케이션을 동시에 운영하고 주요 지표를 수집하여 비교

 

테스트 하기 전에 기존의 오브젝트들 싹 다 지워보자

kubectl delete all --all (테스트 환경에서만 해야돼)

canary 업데이트 전략을 테스트해보자

= v0.1 버전이랑 v0.2버전을 동시에 서비스 하는거임.

kubectl apply -f . 하면 내 위치에 있는 폴더의 모든 yaml 다 생성함

 

카나리 업데이트 테스트 (249P)

- 롤링업데이트/블루그린/재생성 모두 업데이트 시 과정은 다르나, 최종적으로 모두 변경되는 방식

- 테스트를 통해서 변경에 이상이 없는지 확인하는 방식으로 카나리 테스트 사용

- k8s에서 카나리 방식 업데이트를 수행하기 위한 방식 : 두 개의 디플로이먼트를 사용

             - 첫 번째 Deployment: 운영버전

             - 두 번째 Deployment: 테스트 버전

- 카나리 테스트용 디플로이먼트의 개수를 1개 정도 생성하고, 서비스는 두 디플로이먼트에 의해 생성된 파드를 모두 연결하도록 설정

- 테스트 중 카나리 디플로이먼트에 이상 발생 시 카나리 디플로이먼트는 복제본 개수를 0으로 감소

- 카나리 테스트 중 이상없이 업데이트가 수행되었을 경우는 카나리 디플로이먼트와 운영 디플로이먼트의 개수를 조정하여 새로운 버전으로 변경될 수 있도록 수정

- 카나리 테스트 완료 후 카나리용 디플로이먼트는 카나리 테스트 용도로만 사용하므로 복제본 개수를 줄이고, 운영 디플로이먼트의 업데이트를 수행하여 버전 업데이트 수행

 ex) kubectl set image deployment/k8s-testapp testapp=arisu1000/simple-container-app:v0.2

 

 

 

 

질문) deployments.apps에 apps 왜붙음?

kubectl get resources 하면

kubectl api-resources 하면 나옴 -> 글구 이거 들어가보면 단축키 뭔지도 알 수 있어

저기에 apps 있지? 근데 사실 안붙여도 된대. 강사님은 그냥 붙이고 싶대. ㅋㅋ

apps 이게 API Group이야.

 

 

 

 

kubectl scale deployment k8s-testapp --replicas=1 (실제 운영서버)

kubectl scale deployment k8s-testapp-canary --replicas=5 (테스트 서버)

 

운영 서버를 줄이고 테스트 서버를 늘렸다가, 테스트 다 끝나면 운영 서버 업데이트하고

테스트 서버 1개로 줄이고 운영 서버 다시 늘리면 됨

 

업데이트는 얼케해? 

kubectl set image deployment/k8s-testapp testapp=arisu1000/simple-container-app:v0.2

저 testapp은 container의 name임

kubectl describe deploy k8s-testapp

2개의 deployment를 하나의 서비스에 연결해서 업데이트 전략을 수행할 수 있다.

 

 

- 디플로이먼트에 의한 업데이트이므로 향후 문제 발생시 롤백 가능

 ex) kubectl rollout history deployment k8s-testapp

      kubectl rollout undo deployment/k8s-testapp --to-revision=[리비전번호]

 

테스트 하고 내가 선택한 오브젝트를 전부 지우고 싶을 때

 

 

 

참고) 사용자화(Customization)

 

1. 이미지 사용자화 : 이미지를 사용자가 원하는 방식으로 작성 (docker)

Dockerfile : 내가 원하는 대로 이미지를 작성

- FROM: 어떤 이미지로부터 작성할 것인가

- RUN: 이미지 빌드 시 실행

- ENTRYPOINT: 빌드 된 이미지로부터 컨테이너 생성 시 실행

- CMD: 빌드 된 이미지로부터 컨테이너 생성 시 실행

- ENV: 환경변수 설정

 

ENTRYPOINT 와 CMD의 특징

1) CMD만 있는 경우

- 이미지로부터 컨테이너 생성 시 CMD에 있는 내용을 실행

- CMD는 여러 개로 작성될 수도 있음

- CMD에 지정된 항목은 재지정 가능

ㄴ docker run -d --name test testimage:latest -- /bin/bash

이걸 하면, 원래 실행되어야 할 명령어가 /bin/bash로 실행이 된대

 

2) ENTRYPOINT만 있는 경우

- 이미지로부터 컨테이너 생성 시 ENTRYPOINT에 있는 내용을 실행

- 기본적으로는 변경 불가 (기본적으로는 무조건 실행된다...)

- 변경 가능 : 별도 옵션으로 지정 --entrypoint

3) CMD와 ENTRYPOINT가 둘 다 있는 경우

- 이미지로부터 컨테이너 생성 시 ENTRYPOINT 및 CMD에 있는 내용을 실행

- ENTRYPOINT는 명령어, CMD는 파라미터

 

테스트용 Dockerfile

FROM busybox:1.34

ENTRYPOINT ["ls"]

CMD ["-l", "/etc/hosts"]

 

docker 테스트를 위한 사용자 계정 설정 수정

$ sudo usermod -aG docker vagrant (이렇게 해도 되고 아니면 명령어 앞에다 항상 sudo 붙여도 됨)

-> 이거 안하면 permission error가 뜸.

로그아웃 후 재 로그인

 

이미지 빌드

docker build -t test .

빌드된 이미지  확인

docker images test:latest(구식 명령어)   docker image ls (새로운 명령어)

docker image inspect test:latest -> 어떤 명령어가 실행될건지도 알 수 있어

inspect 명령어 치면 다 나옴 ㅋㅋ

 

이미지로부터 테스트 컨테이너 실행 테스트

docker run --rm --name testcontainer test:latest

Dockerfile에 입력한대로 ls 실행이 잘 되고 종료된 것을 알 수 있다.

CMD 변경하여 실행 테스트

docker run --rm --name testcontainer test:latest -- /etc/passwd

docker run --rm --name testcontainer test:latest -- /etc/passwd /etc/shadow

(이렇게 많이 쓰는건 아니지만, 테스트할 때 많이 쓴대.)

-> cmd가 통채로 바뀌는거야. 

 

테스트용 Dockerfile

FROM busybox:1.34

ENTRYPOINT ["ls"]

CMD ["-l", "/etc/hosts"] -> CMD ["/etc/passwd"] 이렇게 바뀌는거지.

 

 

 

ENTRYPOINT 및 CMD 변경하여 실행 테스트

docker run --rm --name testcontainer --entrypoint='cat' test:latest -- /etc/passwd (이건 테스트 용도래)

잘 보면, 실행되고 컨테이너가 바로 삭제되어서 그런 컨테이너 없다구 나옴.

 

 

 

쿠버네티스 파드 리소스의 컨테이너 정의에서 ENTRYPOINT, CMD 재지정 방법

ENTRYPOINT(Dockerfile) - command(kubernetes)

CMD(Dockerfile) - args(kubernetes)

두 항목 모두 YAML 리스트 형식으로 작성

 

테스트용 Pod 리소스 custom-test.yaml

apiVersion: v1

kind: Pod

metadata:

  name: custom-test

spec:

  containers:

  - name: custom-test-container

    image: busybox:1.34

    command: <- kubernetes

    - sleep

    args:

    - "10"

busybox 실행하고 10초간 sleep하고 종료된다

 

근데 잘 생각해보면, pod은 실행 상태를 유지하려는 성질이 있다.

그래서 container creating -> running -> completed -> CrashLoopBackOff가 뜸. 

 

왜 CrashLoopBackOff?

왜 뜨냐하면, 일단 completed가 된 순간, busybox가 꺼졌잖아. 그런데 그걸 다시 restart 하려고 해봤자

프로세스가 꺼져있으니까 안켜지지. 그니까 계속 failed가 뜨는거야.

뭘 생각하면 되냐하면, pod에 -dt /bin/bash 이거 안해둔 상태에서 켜면 바로 꺼지잖아?

그걸 restart 백날 해봐. 켜지나. 안켜지지.

 

 

비지박스란?

비지박스(BusyBox)는 유닉스의 명령어 일부를 집대성하여, 타 운영체제에서 유닉스 명령어를 사용할 수 있도록 만들어 주는 소프트웨어입니다.

즉, 명령어가 극히 제한적인 운영체제에 생기를 주는 소프트웨어라 할 수 있겠습니다.

 

일반적으로 안드로이드에 비지박스를 설치하는 이유는 일부 앱이 유닉스 명령어의 일부를 사용하기 때문입니다.

예를 들어 루트 권한을 획득한 애플리케이션이 unzip, wget과 같이 안드로이드에 없는 명령어를 요구하면, 오류가 날 것입니다.

이것이 안드로이드에 비지박스를 설치하는 첫 번째 이유입니다.

 

또 다른 이유는 익숙한 명령어를 사용하기 위함입니다.

BusyBox에 있는 명령어의 대부분은 리눅스와 호환됩니다.

리눅스 명령어를 다룰 줄 안다면, 안드로이드에서도 능숙하게 다룰 수 있을 것입니다.

https://openacademicnet.tistory.com/27

 

 

 

 

실행명령 사용자화 테스트 리소스 myweb.yaml

apiVersion: v1

kind: Pod

metadata:

  name: myweb

spec:

  containers:

  - name: myweb-container

    image: ghcr.io/c1t1d0s7/go-myweb

    ports:

    - containerPort: 8080

      protocol: TCP

 

여기서 curl로 확인해보려고 하는데 안되네? 저번에도 이런 증상 있었는데.

 

아 저번에 내가 뭔 테스트 하면서 bash 건드렸더니 이런가봐.

아나... eks 테스트한답시고 control-plane에다가 깔았더니 이러나보네. ㅡㅡ.

뭐가 꼬였었나봐.

snapshot으로 처음 setting한 상태로 돌아가니까 잘 된다.

(snapshot 필수!)

 

 

자. 지금 kube-node2에 myweb pod가 배포가 되었지?

그러면 myweb container를 실행하기 위해서, kube-node2에는 반드시 myweb 이미지가 들어가야해.

그걸 확인해보자.

 

sudo docker image inspect ghcr.io/c1t1d0s7/go-myweb 해보면 cmd랑 entrypoint가 어떻게 정의되었는지도 알 수 있어.

 

 

포트 변경을 args로 지정하도록 수정

apiVersion: v1

kind: Pod

metadata:

  name: myweb

spec:

  containers:

  - name: myweb-container

    image: ghcr.io/c1t1d0s7/go-myweb

    ports:

    - containerPort: 8888 (아래에서 서비스를 8888로 열 것이기 때문에, 컨테이너도 8888로 열어줘야한다)

      protocol: TCP

    args:

    - -port=8888

이렇게 하면 안된다는 소리

만약 containerPort: 8000이고 -port=8888로 하면

서비스는 8888로 들어오는데, pod은 8000로 열려서 unmatching 해진당..

 

완전 개꿀팁)

서비스의 port를 변경해야할 필요가 있는 서비스 같은 경우에는, 굳이 이미지를 build 하기 위한

Dockerfile을 변경해서 다시 이미지 build하고 이럴 필요가 없이

그냥 args로 -port 넣어주면 된다.

 

기존의 pod을 삭제하고 새로 만들자. 이때 --now를 왜 붙였어? 조금이라도 더 빨리 지워지게 하려고 붙이셨대.

--now=false: If true, resources are signaled for immediate shutdown (same
as --grace-period=1).

 

차이가 꽤 큼. 무조건 붙이는게 좋겠다. ㅋㅋ (체감상 한 4-5초는 차이나는듯?)

 

원래 서비스 포트는 따로 지정 안하면 80으로 열릴거 아냐? -> ㄴㄴ 얘는 8080이 default port

그럼 args의 port를 지워보자.

 

오개념

잘 보면 curl 192.168.119.130:8080을 해도 return값을 반환 안하는 것을 알 수 있다.

containerPort는 8888을 열어줬는데 8080으로 접근이 된다!!!

containerPort는 방화벽의 개념이 아니래.

8888 연다고 그거 제외하고 접근이 안되는게 아니고, 8888도 들어올 수 있다 하고 알려주는 개념이래

음..? 누구한테 알려줌? (정보를 제공하는 개념이라는데... 좀 이해가 안가고 모호함)

 

이 중 "spec.containers[].ports[].containerPort"에서 설정한 부분이 컨테이너에서 listen하고 있는 포트가 됩니다.

https://real-dongsoo7.tistory.com/135

ㄴ 이 부분 때문에 헷갈렸는데, 정확히 말하면 containerPort는 declarative value에 가깝다.

https://blog.hojaelee.com/186

 

containerPort는 방화벽이 아니다. (Rather, optional/informational)

강사님이 containerPort는 방화벽의 역할이 아니고 listening port를 보여주는 역할이라고 하셔서 먼 소리지? 했다. 그래서 좀 더 자세하게 알아봤다. 우선 선배님들 카톡방에다가 질문을 투척했음 In a n

blog.hojaelee.com

참조할 것!

 

 

 

2. 환경변수를 이용한 사용자화

docker 명령어 실행 시 환경변수 지정

docker run -e <환경변수이름>=<환경변수값> ...

mysql의 경우 환경변수로 패스워드를 넣어줘야한다

 

그럼 매번 pod 배포할 때마다 환경변수를 입력해줘야하나?

경우에 따라 다른데, 매번 똑같은걸 넣어줘야하면, 그냥 Dockerfile의 환경 변수에 넣어주면 되는거야.

자동으로 되도록.

 

 

 

환경변수를 지정하는 이미지 생성(Dockerfile)

FROM busybox:1.34

ENTRYPOINT ["sleep"]

CMD ["1000"]

ENV MYENV1="Hello World"

이미지 빌드

docker build -t envtest .

이미지 확인

docker images envtest

docker image inspect envtest

 

이미지 실행

docker run -d --rm --name testcontainer envtest

 

환경변수 확인

docker exec testcontainer env

환경변수의 PATH... 명령어를 치기 위해서 들어가있음. 

내가 입력한 MYENV1도 들어가있고, HOME도 들어가있음

그래서 잘 보면...

이렇게 하면 내 HOME의 위치가 나옴. (왜 /root가 안나와? 아마 덧씌워진듯 vagrant껄루)

 

 

 

근데 /bin/bash는 안들어가지는거보니까, 이 container image에는 /bin/bash가 없나봐

검증해보자.

진짜 bash가 없음... ㅋㅋㅋㅋ 개어이없네....

대신 sh는 있다... 그래서 /bin/sh는 접속이 됐던거야.

 

 

 

내가 exec의 용도를 컨테이너에 접속하는 것으로만 생각하고 있어 자꾸!!!!

docker exec testcontainer env

이렇게 명령어를 쳐서 결과 값을 리턴받게 할 수도 있어!

 

ex) docker exec testcontainer ls -al |grep bash

 

 

기존 컨테이너 삭제

docker rm -f testcontainer

 

환경변수를 지정하는 컨테이너 생성

 docker run -d --rm -e MYENV2="Merong" --name testcontainer envtest

환경변수 확인

docker exec testcontainer env

 

Quiz)

Dockerfile에서 MYENV="Hello World"로 해두고

docker run -d --rm -e MYENV="I'm Hojae"로 하면 어떻게 될까?

overwrite가 될까? 에러가 날까?

-> overwrite 된다.

 

대부분의 명령어는 우선순위가 있어.

 

예를 들어, 처음 컨테이너 이미지에 환경 변수가 있을 수도 있고

Dockerfile에 환경 변수를 넣을 수도 있고

실행할 때 환경 변수를 넣을 수도 있고

k8s에서 배포할 때 환경 변수를 넣을 수도 있어.

-> 보통 나중에 실행시키는걸로 overwrite됨.

그리고 대개, 지금 당장 명령어로 실행시키는게 우선 순위가 가장 높다고 보면 됨.

 

 

 

 

 

k8s에서 파드 생성시 환경변수 설정

테스트용 파드 (myweb-env.yaml)

apiVersion: v1

kind: Pod

metadata:

  name: myweb

spec:

  containers:

  - name: myweb-container

    image: ghcr.io/c1t1d0s7/go-myweb

    ports:

    - containerPort: 8080

      protocol: TCP

    env:

    - name: MESSAGE

      value: "Customized Hello World!"

    - name: MYENV1

      value: "Hello World"

    - name: MYENV2

      value: "Merong"

 

 강사님이 bash랑 sh 없대 ㅋㅋ 아주 최소로 만들어진거라

아마 이 컨테이너 이미지가 웹으로 환경변수 출력하게 만들어진건가봄

그래서 사실 exec로 안에 직접 들어가서 확인할 방법은 없고 curl로 확인하든가

kubectl describe pod myweb으로 확인할 수도 있다.

혹은 kubectl get pod myweb -o yaml 이렇게 해도 됨.

 

 

교재에서는 그냥 컨피그맵으로 넘어가보자! 이래가지고 이해가 안가는데

그래서 위에 환경 변수쪽을 자세하게 설명해주신거래.

그럼 컨피그맵이 먼가 key랑 value를 저장하기 위한건가봄.

 

 

 

 

 

컨피그맵(ConfigMap) 설정이 들어있는 Map이다!

컨테이너에 필요한 환경 설정을 컨테이너와 분리해서 제공하는 기능

- 사용자가 필요로 하는 설정 등을 저장할 수 있는 저장공간

- etcd 저장소에 저장되므로, 키/값 구조를 가져야 함

 

컨피그맵-키-값

 

configmap의 목적?

여기에 데이터를 저장해서 장기 보관하자는게 아니고, 쿠버네티스 안에 있는거니까

클러스터 내부에서 데이터를 조금 더 쉽게 가져가게 하려고 하는거임.

 

1)  키/밸류 입력

kubectl create configMap <컨피그맵 이름> --from-literal=<키이름>=<값>

ex) kubectl create configmap myconf1 --from-literal=key1=value1

ex) kubectl create configmap myconf2 --from-literal=key1=value1 --from-literal=key2=value2

 

configmap을 만들었어. 

근데 kubectl get all 하면 안나와. 왜???

알다시피(??라고 강사님이 말씀) 저 all이 진짜 all이 아니고, 자주 쓰이는 리소스만 보여주는거래.

INGRESS 뭐 이런거 안보임.

 

 

kubectl get configmaps하면 들어간 데이터 갯수만 나오고

kubectl describe configmaps myconf1 하면 진짜 데이터가 나옴

 

 

 

 

 

2) 파일을 사용 (파일명을 키로 사용)

kubectl create configMap <컨피그맵 이름> --from-file=<파일이름>

파일이름이 키로 지정 / 파일 내용이 값으로 지정

(언제 써? 리눅스 시스템에서는 많은 항목들이 key-value 형태가 파일로 저장된 경우가 많대. 그때 configmap 저장하면 된대)

ex) echo value1 > key1

ex) kubectl create configmap myconf3 --from-file=key1

             // 이 경우 파일명인 key1이 키, 파일 내용인 value1이 값으로 저장

3) 파일을 사용 (별도의 키 지정)

kubectl create configMap <컨피그맵 이름> --from--file=<키이름>=<파일이름>

ex) echo value1 > key1.txt

ex) kubectl create configmap myconf4 --from-file=key1=key1.txt

             // 원 파일명인 key1.txt 대신 지정한 key1이 파일명이 됨

4) 디렉토리와 디렉토리 내 파일을 사용

 

3번의 경우, 파일 하나만 가져오는거잖아. 그런데 여러 개 파일 가져오고 싶을 수도 있잖아.

 

mkdir conf

$ echo value1 > conf/key1

$ echo value2 > conf/key2

$ echo value3 > conf/key3

$ kubectl create configmap myconf5 --from-file=conf

 

이렇게 하면 한방에 여러 파일을 읽어와서 configmap으로 만들 수 있어.

 

5) 리소스 파일을 작성 (YAML)

개행이 안되어서 저렇게 나오는거임. ㅋ

 

 

 

 

ConfigMap 데이터 불러오기 방식 (파드 기준)

1) 환경변수를 불러올 컨테이너의 ENV항목에서 지정한 컨피그맵의 키를 가져오도록 설정

...

    spec:

      containers:

      - name: testapp

        image: arisu1000/simple-container-app:latest

        ports:

        - containerPort: 8080

        env:

        - name: DEBUG_LEVEL

          valueFrom:

            configMapKeyRef: (configmap안에 있는 특정 key를 참조하겠다)

              name: config-dev

              key: DEBUG_INFO (해당 configmap에 DEBUG_INFO라는 key가 있는지, 있으면 그걸 가져와서 value로 쓰겠다.)

...

 

kubectl exec -> tab tab 누르면...

tab tab 누르면 저것들이 뜨네?

 

지금 접속 가능한 pods가 나오는거같아.

 

 

여기 잘보면, DEBUG_INFO : debug라고 되어있어. 이거를 가져온거임.

참고) valueFrom 사용법

테스트용 파일 (valuefrom-test.yaml)

apiVersion: v1

kind: Pod

metadata:

  name: testpod

spec:

  containers:

  - name: testpod-container

    image: busybox:1.34

    env:

    - name: NODE_NAME

      valueFrom:

        fieldRef:

          fieldPath: spec.nodeName #(이 pod이 어떤 Node에서 실행되고 있는지)

    - name: POD_NAME

      valueFrom:

        fieldRef:

          fieldPath: metadata.name

    - name: POD_NAMESPACE

      valueFrom:

        fieldRef:

          fieldPath: metadata.namespace

    - name: POD_IP

      valueFrom:

        fieldRef:

         fieldPath: status.podIP

    - name: POD_SERVICE_ACCOUNT

      valueFrom:

        fieldRef:

         fieldPath: spec.serviceAccountName <-이러한 값들이 들어감!

    args:

    - "sleep"

    - "1000"

 

 

 

 

 

파드 리소스 생성 후 확인

kubectl get po -o wide

testpod                      1/1     Running   0          10s     192.168.9.66      kube-node1

 

kubectl exec testpod -- env

...

POD_SERVICE_ACCOUNT=default

NODE_NAME=kube-node1

POD_NAME=testpod

POD_NAMESPACE=default

POD_IP=192.168.9.66

...

 

 

실습문제

 

1. 다음 정보에 따라 각 리소스를 생성하시오. (6 디플로이먼트, 2서비스)

 

종류: 디플로이먼트

복제본 수: 2

이름: webserver-alpha

셀렉터: app=webserver

이미지: ghcr.io/c1t1d0s7/go-myweb

컨테이너 포트: 8080

파드 레이블:

           app: webserver

           envir: prod

           release: alpha

 

종류: 디플로이먼트

복제본 수: 2

이름: webserver-beta

셀렉터: app=webserver

이미지: ghcr.io/c1t1d0s7/go-myweb

컨테이너 포트: 8080

파드 레이블:

           app: webserver

           envir: prod

           release: beta

 

종류: 디플로이먼트

복제본 수: 2

이름: webserver-stable

셀렉터: app=webserver

이미지: ghcr.io/c1t1d0s7/go-myweb

컨테이너 포트: 8080

파드 레이블:

           app: webserver

           envir: prod

           release: stable

 

종류: 디플로이먼트

복제본 수: 1

이름: webserver-beta-dev

셀렉터: app=webserver

이미지: ghcr.io/c1t1d0s7/go-myweb

컨테이너 포트: 8080

파드 레이블:

           app: webserver

           envir: dev

           release: beta

 

종류: 디플로이먼트

복제본 수: 1

이름: webserver-alpha-dev

셀렉터: app=webserver

이미지: ghcr.io/c1t1d0s7/go-myweb

컨테이너 포트: 8080

파드 레이블:

           app: webserver

           envir: dev

           release: beta

 

종류: 디플로이먼트

복제본 수: 1

이름: webserver-stable-dev

셀렉터: app=webserver

이미지: ghcr.io/c1t1d0s7/go-myweb

컨테이너 포트: 8080

파드 레이블:

           app: webserver

           envir: dev

           release: stable

 

종류: 서비스

타입: ClusterIP

이름: svc-alpha

셀렉터: release=alpha

 

종류: 서비스

타입: ClusterIP

이름: svc-prod

셀렉터: env=prod

 

각 구성에 맞게 동작하는지 확인하시오

 

그런데...

port가 겹치니까 안돼.

ClusterIP의 port는 바꿔줘야 하나봐. 사실 이상하긴 했어.

아냐!!!!!!!

안바꿔줘도 돼.

https://blog.hojaelee.com/157

port는 IP에 할당되는거라, IP가 다르면 port가 같아도 상관 없어.

아마 connection refused 뜬 이유는, targetPort를 8080이 아니라 8081 뭐 이렇게 바꿔서 그런거같아.

서비스는 8080으로 돌고있는데 targetPort를 8081로 해서 아마...

 

 

 

정답)

port와 targetPort는 이제 알겠고

아직도 containerPort는 잘 모르겠어. 굳이 저걸 안열어도 서비스의 port로 접근이 된다면

저게 왜 필요한거야?

 

 

2. 다음 조건에 따라 각 ConfigMap을 생성하시오.

 

이름: testconf1

키: MYIP

값: 100.100.100.100

 

이름: testconf2

키: hosts

값: /etc/hosts 파일의 내용

 

이름: testconf3

(사전에 /etc/passwd, /etc/group, /etc/hosts 파일을 ~/myfile로 복사하여 사용)

키: 각 파일이름

값: 각 파일 내용

 

명령어로 입력
파일로 입력

 

 

 

여러 파일을 동시에 입력

  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기