변수 하나 가져오기 vs 변수 통채로 가져오기

deployment-config01.yaml과 deployment-config02.yaml의 차이

 

configmap의 용도는? 말 그대로 config를 저장하기 위한 공간 정도인듯.

환경 변수를 저장하기 위한 공간.

 

deployment-config03.yaml

 

컨피그맵을 사용한 파일 볼륨 마운트

 

만들어서 들어가보면 링크 걸려있음

구조를 왜 이렇게 만들었는지는 강사님도 모른대.  

 

 

실습: nginx 설정 파일을 컨피그맵에 저장 후 파드에서 볼륨으로 마운트

 

참고) nginx 설정파일 위치

기본 - /etc/nginx/nginx.conf

추가 - /etc/nginx/conf.d/*.conf

  

nginx.conf (http 압축해서 보내는 기능 활성화)

server {

  listen 80;

  server_name myapp.example.com;

  gzip on;

  gzip_types text/plain application/xml;

  location / {

    root /usr/share/nginx/html;

    index index.html;

  }

}

 

kubectl create configmap nginx-gzip-conf --from-file=nginx-gzip.conf=nginx.conf

 

configmap에 단순히 key, value만 들어가는게 아니었어. conf 파일도 통채로 들어가네!

 

gzip on; <- 압축 기능을 킨당

 

$ kubectl get configmaps nginx-gzip-conf

NAME              DATA   AGE

nginx-gzip-conf   1      19s

 

$ kubectl describe configmaps nginx-gzip-conf

Name:         nginx-gzip-conf

Namespace:    default

Labels:       <none>

Annotations:  <none>

 

Data

====

nginx-gzip.conf

----

server {

  listen 80;

...

 

 

nginx 파드 생성

apiVersion: v1

kind: Pod

metadata:

  name: nginx-pod

spec:

  containers:

  - name: nginx-pod-container

    image: nginx

    ports:

    - containerPort: 80

      protocol: TCP

    volumeMounts:

    - name: nginx-gzip-volume #(2. 여기서 마운트 시킨다)

      mountPath: /etc/nginx/conf.d #이렇게 활용할 수 있구나!!!

  volumes:

  - name: nginx-gzip-volume #(1. configMap에서 conf파일 가져와서 볼륨 만들고 여기서 만든 볼륨을)

    configMap:

      name: nginx-gzip-conf

오류! 왜? volumeMounts의 name과 Volumes의 name을 동일하게 맞춰줘야해

-> 자꾸 CrashLoopBackOff 뜨는데 이유를 모르겠다.

심지어 강사님이 준 코드를 그대로 복붙을 해도 안돼. 왜일까?

-> 이미지 문제였다. image를 ubuntu/apache2로 바꾸니까 잘 돼.

뭐지... 

 

이미지 바꾸니까 잘 됨. -ㅅ-

 

xx.conf파일을 configMap의 객체로 넣고, 이 객체를 다시 Volume으로 만들어서 /etc/nginx/conf.d 디렉토리 경로에 mount 하겠다.
/etc/nginx/conf.d/경로에 쓰일 파일의 이름은 nginx-gzip.conf가 되는거야. 왜? configmap 만들 때 alias 해줬으니깐!

 

서버 구동 후 파드 IP 확인

kubectl get pod -o wide

 

일반 요청 헤더 확인

$ curl -I http://192.168.233.208

이렇게 하면 헤더만 나옴

 

gzip 압축 요청 헤더 포함 요청

$ curl -H "Accept-Encoding: gzip" -I http://192.168.233.208

이게 무슨 뜻이냐하면

curl -H "Accept-Encoding: gzip" -I http://192.168.233.208

이게 클라이언트단에서 tag에 Accept-Encoding: gzip을 붙여서 보낸거야.

curl의 옵션 중 하나...

그러면 서버에서 어? 클라이언트가 tag에 Accept-Encoding: gzip을 실어서 보냈네?

그럼 나도 gzip으로 압축해주면 되겠구나! 라고 하는거지. (물론 서버에서 지원을 한다는 가정하에)

그리고 실제로 gzip으로 압축을 해서 전송을 하는거야.

그래서 Content-Encoding: gzip을 서버에서 태그로 보낸거쥐.

 

 

참고) 마운트 시 주의할 사항

테스트용 리소스 오브젝트 파일

apiVersion: v1

kind: Pod

metadata:

  name: nginx-pod

spec:

  containers:

  - name: nginx-pod-container

    image: nginx

    ports:

    - containerPort: 80

      protocol: TCP

    volumeMounts:

    - name: nginx-gzip-volume

      mountPath: /etc/rc0.d

  volumes:

  - name: nginx-gzip-volume

    configMap:

      name: nginx-gzip-conf

이와 같이 리소스를 생성할 경우, /etc/rc0.d와 같이 기존 파일이 있는 경로에 마운트를 실행하므로, 리눅스 mount의 기본 특성과 같이 기존에 있는 파일은 마운트 이후에는 접근할 수 없게 됨.

 

참고로 /etc/rc0.d는 디렉토리다..

 

(기존의 파일이 삭제되는건 아니다. 다만, 기존의 파일 주소를 새로운 파일 주소가 대체하면서 링크를 mount를 해제하기 전까지는 새로운 파일에 접근하게 된다.)

 

-> 이걸 방지하기 위해 다른 설정을 해줘야돼.

 

 

이번에는 기존의 파일도 갖고 있으면서 새로운 파일도 마운트를 하도록 해본다!

 

apiVersion: v1

kind: Pod

metadata:

  name: nginx-pod

spec:

  containers:

  - name: nginx-pod-container

    image: nginx

    ports:

    - containerPort: 80

      protocol: TCP

    volumeMounts:

    - name: nginx-gzip-volume

      mountPath: /etc/rc0.d/nginx-gzip.conf

      subPath: nginx-gzip.conf

  volumes:

  - name: nginx-gzip-volume

    configMap:

      name: nginx-gzip-conf

 

-> 기존 방식의 경우 디렉토리 전체를 갈아치우는 방식이었다면, 이건 개별 파일을 마운트하겠다는거래.

 

 

mountPath에 파일 전체 경로 명시 후, 파일명을 subPath에 지정할 경우, 디렉토리 마운트 방식이 아닌 파일 개별 마운트를 사용하여, 기존 파일과 함께 마운트되게 할 수 있음. 개별 파일 마운트 방식을 사용하기 때문에 기존 디렉토리 마운트와 마운트되는 방식이 다름

 

오개념)

나는 kubectl apply -f xxx.yaml하면 무조건 새롭게 업데이트가 되는건줄 알았는데 그게 아니네?

 

지우고 다시 해야돼. ㄷㄷ.

 

이렇게 하면 덮어씌워지지 않고 잘 들어간다.

 

 

그래서 Configmap의 마운트 방식은 2가지가 있다.

 

디렉토리 마운트 방식

1) 컨피그맵 키 항목별 파일을 마운트위치/..[날짜시간] 디렉토리 생성하여 저장

2) 마운트위치 내 ..[날짜시간] 디렉토리의 링크를 ..data 이름으로 생성

3) ..data 링크에 연결된 디렉토리 내 각 파일에 대한 링크를 마운트위치 내 생성

(1,2,3을 내가 직접 해야된다는게 아니고, 자동으로 저렇게 만들어준다는 뜻임)

 

개별파일 마운트 방식

- 지정한 파일이름으로 직접 마운트 수행

 

여러 설정 파일을 configmap에 넣어서 많이 활용한다.

파일로 들어갈 수 있는건 어떤거나 다 넣을 수 있다.

물론 텍스트 형태의 파일을 넣어야겠지!

 

 

 

 

 

 

시크릿

 

configmap과 비슷하다. 그런데 데이터를 어떻게 다루느냐에 차이가 있다.

얘도 etcd에 저장되는거임.

configmap과 차이는, configmap이 보안이 중요하지 않은 데이터를 저장한다고 하면

시크릿은 보안이 중요한 패스워드, SSH키, 인증정보, 토큰등 민감한 정보를 저장하기 위해서 사용한다.

 

configmap과의 차이는 시크릿은 "type이 있다"

 

참고)

echo hello

echo의 경우 기본적으로 \n을 포함하고 출력한다.

echo -n hello 하면 \n을 빼고 출력한다.

이런식으로 됨 ㅋㅋ

 

 

시크릿 생성 명령

$ kubectl create secret <타입> <시크릿이름> [--from-literal=<키>=<값>] [--from-file[=<키>]=<파일이름>]

시크릿 데이터 저장 후 저장된 데이터 확인

- kubectl get secret <시크릿이름> -o yaml

- 시크릿에 저장된 데이터는 Base64 방식으로 인코딩됨

password가 인코딩되어서 저장되었다.
decode 정상적으로 잘 된다.

 

Base64 인코딩 규칙 (=총 64개의 글자로 인코딩을 하겠다)

 

컴퓨터에서 정보의 최소 단위는? bit!

근데 bit단위로 우리가 생각하기엔 너무 어려우니까 보통은 1byte를 최소 단위로 보지.

그러면 2^8=256->0~255까지 

근데 처음 컴퓨터를 만든 사람이 알파벳을 썼잖아.

그러니까 a-zA-Z0-9에다가 일부 특수문자 다 해도 2^6이면 좀 부족 2^7이면 엇비슷한 상황.

그리고 컴퓨터에서는 숫자가 1,2,4,8 이런식으로 가는게 좋아서 2^8로 선택한거래 (이건 좀 이상?)

 

 

 

- 모든 이진법 데이터를 입력 가능한(텍스트로 표현 가능한) 포맷으로 변경

- 사용하는 글자가 총 64개 (A-Z, a-z, 0-9, +, /), 패딩 (=)  [2^6=64]

- 일반 Byte 단위의 데이터를 Base64로 변환 : 3 바이트 → 4 Base64

ㄴ 3 * 8bits = 4 * 6bits = 24

ABC 3글자에서 QUJD 4글자로 바뀌었당

 

default-token-hs4x4는 내가 안만들었는데, 자동으로 생긴거임. 쿠버네티스 만들어진 시점과 동일하대. 그러니까 40일 전에 만들어진거임... 흑흑. 빨리 볼걸 인강.....ㅜ

 

시크릿에는 암호화가 적용되어있지 않다. 그냥 이 파일 그대로 etcd에 저장되는거야.

-> 그래서 암호화를 위해서 인증 같은 부분을 적용해줘야돼 (이건 우리가 다루지 않는대. 시크릿 저장소 암호화)

헐 터미널에서도 찍어볼 수 있네? ㅋㅋ

 

그럼 궁금한 점.

왜 굳이 base64로 인코딩을 해서 저장하지?

ㄴ 이것에 대한 답은 모르겠는데 (추측컨대, 쿠버네티스가 다양한 아키텍쳐 위에서 돌아가니까..?)

아래 게시글은 Secret을 정말 Secret 하게 만들기 위해서 필요한 조건이 쓰여있다.

 

https://togomi.tistory.com/11

 

Kubernetes Secret은 정말 Secret일까?

개발을 하다 보면 아이디, 비밀번호 등 민감 정보가 필요할 때가 필연적으로 생긴다. 쿠버네티스에서는 이러한 경우를 위해 시크릿을 사용한다. 공식문서에는 다음과 같이 쓰여있다. 쿠버네티

togomi.tistory.com

요약하면 1) RBAC으로 접근 제어 2) 암호화 기능 활성화(EncryptionConfiguration)해서 etcd에 저장

 

 

 

Secret에 Docker hub 계정 정보를 입력하여 사용

 

Docker Hub 계정 생성: https://10minemail.com/ko/

 

kube-control1에서 docker 명령을 사용하여 이미지 업로드

$ docker login

$ docker info          // 로그인 확인

 

현재 이미지 확인 및 업로드 할 이미지 태그

$ docker images

$ docker tag busybox:1.34 <계정명>/<레포지토리명>:test

ex) $ docker tag busybox:1.34 jejiw79934/private:test

 

이미지 업로드

$ docker push <계정명>/<레포지토리명>:test

ex) $ docker push jejiw79934/private:test

 

도커 로그아웃

$ docker logout

 

이미지 삭제

$ docker rmi <계정명>/<레포지토리명>:test

ex) $ docker rmi jejiw79934/private:test

 

쿠버네티스에서 Docker Hub 또는 Private 레지스트리의 계정정보를 저장하기 위한 시크릿 생성

$ kubectl create secret docker-registry <시크릿이름> --docker-username=<사용자이름> --docker-password=<패스워드> --docker-email=<이메일> --docker-server=<레지스트리 주소>

$ kubectl create secret docker-registry dockersecret --docker-username='jejiw79934' --docker-password='Qwerty!23456' --docker-email='jejiw79934@superyp.com' --docker-server='https://index.docker.io/v1/'

 

생성한 시크릿 리소스 확인

$ kubectl get secret

$ kubectl describe secret dockersecret

$ kubectl get secret dockersecret -o yaml

 

교재 소스 내부 내용 수정(deployment-secret03.yaml)

  template:

    metadata:

      labels:

        app: secretapp

    spec:

      containers:

      - name: testapp

        image: jejiw79934/private:test

        ports:

        - containerPort: 8080

      #imagePullSecrets:

      #- name: dockersecret

 

리소스 생성 및 확인

$ kubectl apply -f deployment-secret03.yaml

$ kubectl get pod --watch

 

리소스 설정에서 imagePullSecrets항목 주석 제거 후 재실행

      #imagePullSecrets:

      #- name: dockersecret

 

생성된 파드가 이미지를 제대로 로드하는지 확인

$ kubectl get pod -o wide

 

파드가 생성된 노드에서 이미지가 다운로드 되어 있는지 확인

$ ssh vagrant@<노드이름>

$ sudo docker images | grep private

 

디플로이먼트 replicas 수정하여 다른 노드에서도 확인

 

 

인그레스를 사용한 SSL 구성

- 인그레스에서 SSL 처리가 되고, 각 파드에서는 인그레스를 통해 HTTP로 처리되는 구성

- 인그레스에서 SSL 처리를 위한 인증서 정보를 시크릿으로 저장

 

SSL 구성에 사용할 인증서 및 키 생성

$ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt "/CN=kube-book.com"

 

생성한 키 및 인증서를 시크릿으로 저장

$ kubectl create secret tls kube-book-secret --key tls.key --cert tls.crt

 

생성한 시크릿 확인

$ kubectl describe secrets kube-book-secret

 

인그레스에 사용할 리소스 생성

$ kubectl apply -f ~/kubernetes-book-sample/deployment/deployment-nginx.yaml

$ kubectl expose deployment nginx-deployment --name s1

 

인그레스 컨트롤러 생성

$ kubectl apply -f ~/kubernetes-book-sample/ingress/ssl/ingress-ssl.yaml

 

인그레스 컨트롤러 확인

$ kubectl get ingress

 

인그레스 컨트롤러를 사용한 https 연결 확인

$ curl --resolve kube-book.com:443:192.168.56.21 -k https://kube-book.com

 

자세한 연결정보 확인

$ curl --resolve kube-book.com:443:192.168.56.21 -vIk https://kube-book.com

 

 

 

 

실습예제

 

1. 다음 컨피그맵을 생성하시오.

컨피그맵 이름: myhosts-config

키: myhosts

내용:

127.0.0.1       localhost

::1     localhost ip6-localhost ip6-loopback

 

 

2. 1번에서 생성한 컨피그맵을 파일로 사용하는 파드를 생성하는 디플로이먼트 리소스를 작성하시오.

디플로이먼트 이름: deploy-myhosts

복제본 개수: 1

셀렉터: app=webserver

이미지: nginx:latest

컨테이너 포트: 80

파드 레이블:

      app: webserver

마운트 할 위치: /etc/myhosts

 

 

3. 다음과 같이 동작하기 위한 컨피그맵 및 파드 리소스를 작성하시오.

파드 이름: myhttpd

컨테이너포트: 8080

이미지: httpd:2.4

 

httpd 기본 설정파일을 수정하여 컨피그맵에 저장하시오.

- 변경내용: 웹 서버 실행 포트를 8080으로 변경

httpd 설정파일 위치: /usr/local/apache2/conf/httpd.conf

컨피그맵에 저장된 httpd 설정을 파드에 반영하여 웹서버가 실행되도록 파드를 작성하시오.

 

 

4. Docker hub private레지스트리에 저장된 private 이미지를 사용하는 디플로이먼트 리소스를 작성하시오

원본이미지: arisu1000/simple-container-app:latest

원본이미지를 <계정명>/<Private레포지토리명>:arisu 이름으로 태그를 설정

태그 한 이미지를 Docker hub Private 레포지토리로 업로드

 

생성할 디플로이먼트 리소스

이름: arisu-deployment

이미지: <계정명>/<Private레포지토리명>:arisu

복제본 수: 3

셀렉터: app=arisu

컨테이너포트: 8080

파드 레이블: app=arisu

 

 

참고

 

1. myhosts 파일을 생성하고 내용을 입력한 후, 컨피그맵으로 저장

 

$ cat > myhosts

127.0.0.1       localhost

::1     localhost ip6-localhost ip6-loopback

 

$ kubectl create configmap myhosts-config --from-file=myhosts

 

 

 

 

2. 컨피그맵을 볼륨으로 마운트하도록 설정. /etc 경로는 다른 파일이 있는 경로이므로, /etc/myhosts 파일로 개별 마운트되도록 설정

$ vi deploy-myhosts.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy-myhosts
spec:
  replicas: 1
  selector:
    matchLabels:
      app: webserver
  template:
    metadata:
      labels:
        app: webserver
    spec:
      containers:
      - name: myhosts-container
        image: nginx:latest
        ports:
        - containerPort: 80
          protocol: TCP
        volumeMounts:
        - name: myhosts-config-volume
          mountPath: /etc/myhosts
          subPath: myhosts
      volumes:
      - name: myhosts-config-volume
        configMap:
          name: myhosts-config

 

$ kubectl exec -it <파드이름> -- ls -l /etc/hosts /etc/myhosts

           // 마운트 여부 확인

 

 

 

3. 수정한 httpd.conf 파일을 컨피그맵으로 저장 후 볼륨으로 파드에 마운트

 마운트할때 개별 파일로 마운트되도록 주의: subPath

 

$ docker run -d --rm --name httpd httpd:2.4         

// httpd:2.4 이미지를 사용한 컨테이너 실행

$ docker cp httpd:/usr/local/apache2/conf/httpd.conf .

           // 이미지로부터 httpd.conf 파일을 호스트로 복사

$ vi httpd.conf

           // 포트 설정을 80에서 8080으로 변경

      // Listen 80 => Listen 8080

$ kubectl create configmap httpd-conf --from-file=httpd.conf

           // httpd.conf 파일로부터 컨피그맵 생성

$ cat myhttpd.yaml

           // 파드 오브젝트 파일 작성

apiVersion: v1
kind: Pod
metadata:
  name: myhttpd
spec:
  containers:
  - name: myhttpd-container
    image: httpd:2.4
    ports:
    - containerPort: 8080
      protocol: TCP
    volumeMounts:
    - name: httpd-conf-volume
      mountPath: /usr/local/apache2/conf/httpd.conf
      subPath: httpd.conf
  volumes:
  - name: httpd-conf-volume
    configMap:
      name: httpd-conf

 

$ kubectl create -f myhttpd.yaml

           // 파드 실행

$ curl <파드IP>:8080

           // 설정 확인

 

 

 

 

4. 원본 이미지 다운로드 - 이미지 태그 - Dockehub 로그인 후 push

$ docker image pull arisu1000/simple-container-app:latest

$ docker tag arisu1000/simple-container-app:latest <계정명>/<private레포지토리명>:arisu

$ docker login

$ docker push <계정명>/<private레포지토리명>:arisu

$ docker logout

 

DockerHub 프라이빗 저장소에 접근하기 위한 시크릿 생성

$ kubectl create secret docker-registry dockersecret --docker-username='<계정ID>' --docker-password='<계정패스워드>' --docker-email='<계정EMAIL>' --docker-server='https://index.docker.io/v1/'

 

생성한 시크릿을 사용하여 이미지를 받아와 파드를 실행하는 디플로이먼트 오브젝트 파일 작성

$ vi deploy-private.yaml

           // image 정보를 본인 정보로 수정

apiVersion: apps/v1
kind: Deployment
metadata:
  name: private
spec:
  replicas: 3
  selector:
    matchLabels:
      app: arisu
  template:
    metadata:
      labels:
        app: arisu
    spec:
      containers:
      - name: private-container
        image: <계정ID>/<private레포지토리이름>:arisu
        ports:
        - containerPort: 8080
      imagePullSecrets:
      - name: dockersecret

 

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