변수 하나 가져오기 vs 변수 통채로 가져오기
deployment-config01.yaml과 deployment-config02.yaml의 차이
configmap의 용도는? 말 그대로 config를 저장하기 위한 공간 정도인듯.
환경 변수를 저장하기 위한 공간.
컨피그맵을 사용한 파일 볼륨 마운트
만들어서 들어가보면 링크 걸려있음
구조를 왜 이렇게 만들었는지는 강사님도 모른대.
실습: 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
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
-> 자꾸 CrashLoopBackOff 뜨는데 이유를 모르겠다.
-> 이미지 문제였다. image를 ubuntu/apache2로 바꾸니까 잘 돼.
뭐지...
서버 구동 후 파드 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을 붙여서 보낸거야.
그러면 서버에서 어? 클라이언트가 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의 기본 특성과 같이 기존에 있는 파일은 마운트 이후에는 접근할 수 없게 됨.
(기존의 파일이 삭제되는건 아니다. 다만, 기존의 파일 주소를 새로운 파일 주소가 대체하면서 링크를 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 방식으로 인코딩됨
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글자로 바뀌었당
시크릿에는 암호화가 적용되어있지 않다. 그냥 이 파일 그대로 etcd에 저장되는거야.
-> 그래서 암호화를 위해서 인증 같은 부분을 적용해줘야돼 (이건 우리가 다루지 않는대. 시크릿 저장소 암호화)
그럼 궁금한 점.
왜 굳이 base64로 인코딩을 해서 저장하지?
ㄴ 이것에 대한 답은 모르겠는데 (추측컨대, 쿠버네티스가 다양한 아키텍쳐 위에서 돌아가니까..?)
아래 게시글은 Secret을 정말 Secret 하게 만들기 위해서 필요한 조건이 쓰여있다.
요약하면 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 |
'System Engineering > Kubernetes' 카테고리의 다른 글
Helm이란 무엇이고 왜 써야하는가? (0) | 2022.05.17 |
---|---|
Service는 Service Name:port로 접근할 수 있다. (0) | 2022.05.16 |
Kubernetes iceberg: the bigger picture of what you might expect while diving deeper… (0) | 2022.04.29 |
쿠버네티스 네트워크 오개념 -1 (routing에 관해서) (0) | 2022.04.29 |
쿠버네티스 네트워크 분석 좋은 글 (tcp-dump) (0) | 2022.04.29 |
최근댓글