20220524 필기노트

강재민·2022년 5월 24일
0

필기노트

목록 보기
14/23

정적 프로비저닝


STATUS가 Available인거 확인


create순서는 pv pvc rs 순서..
구조를 그려보면 이렇다

pvc와 pv가 bound상태에서 pv를 지우려고하면 안지워진다
pvc를 먼저 지워야함

그리고 재사용은 안됨


x 곱하기 표시는 몇 번 시도했는지 임
이제 삭제하고 마무리..
만약 pv를 먼저 지우게 되면 포그라운드에서 멈취있게 된다.
터미널 하나 더 열어서 pvc를 지우면 그제야 지워지게 됨


동적 프로비저닝

동적 프로비저닝 개념을 그려보면

https://rook.io/

vagrant halt로 VM을 먼저 중지시키고

Vagrant.configure("2") do |config|
	# Define VM
	config.vm.define "k8s-node1" do |ubuntu|
		ubuntu.vm.box = "ubuntu/focal64"
		ubuntu.vm.hostname = "k8s-node1"
		ubuntu.vm.network "private_network", ip: "192.168.100.100"
		ubuntu.vm.provider "virtualbox" do |vb|
			vb.name = "k8s-node1"
			vb.cpus = 2
			vb.memory = 4000
			unless File.exist?('./.disk/ceph1.vdi')
				vb.customize ['createmedium', 'disk', '--filename', './.disk/ceph1.vdi', '--size', 10240]
			end
			vb.customize ['storageattach', :id, '--storagectl', 'SCSI', '--port', 2, '--device', 0, '--type', 'hdd', '--medium', './.disk/ceph1.vdi']
		end
	end
	config.vm.define "k8s-node2" do |ubuntu|
		ubuntu.vm.box = "ubuntu/focal64"
		ubuntu.vm.hostname = "k8s-node2"
		ubuntu.vm.network "private_network", ip: "192.168.100.101"
		ubuntu.vm.provider "virtualbox" do |vb|
			vb.name = "k8s-node2"
			vb.cpus = 2
			vb.memory = 3000
			unless File.exist?('./.disk/ceph2.vdi')
				vb.customize ['createmedium', 'disk', '--filename', './.disk/ceph2.vdi', '--size', 10240]
			end
			vb.customize ['storageattach', :id, '--storagectl', 'SCSI', '--port', 2, '--device', 0, '--type', 'hdd', '--medium', './.disk/ceph2.vdi']
		end
	end
	config.vm.define "k8s-node3" do |ubuntu|
		ubuntu.vm.box = "ubuntu/focal64"
		ubuntu.vm.hostname = "k8s-node3"
		ubuntu.vm.network "private_network", ip: "192.168.100.102"
		ubuntu.vm.provider "virtualbox" do |vb|
			vb.name = "k8s-node3"
			vb.cpus = 2
			vb.memory = 3000
			unless File.exist?('./.disk/ceph3.vdi')
				vb.customize ['createmedium', 'disk', '--filename', './.disk/ceph3.vdi', '--size', 10240]
			end
			vb.customize ['storageattach', :id, '--storagectl', 'SCSI', '--port', 2, '--device', 0, '--type', 'hdd', '--medium', './.disk/ceph3.vdi']
		end
	end
	# config.vm.define "k8s-docker" do |ubuntu|
	# 	ubuntu.vm.box = "ubuntu/focal64"
	# 	ubuntu.vm.hostname = "k8s-docker"
	# 	ubuntu.vm.network "private_network", ip: "192.168.100.103"
	# 	ubuntu.vm.provider "virtualbox" do |vb|
	# 		vb.name = "k8s-docker"
	# 		vb.cpus = 2
	# 		vb.memory = 2000
	# 	end
	# end

	config.vm.provision "shell", inline: <<-SHELL
	  sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/g' /etc/ssh/sshd_config
	  sed -i 's/archive.ubuntu.com/mirror.kakao.com/g' /etc/apt/sources.list
	  sed -i 's/security.ubuntu.com/mirror.kakao.com/g' /etc/apt/sources.list
	  systemctl restart ssh
	SHELL
end

### File이 존재하느냐 현재 디렉토리의 .disk의 ceph1.vdi라는 파일이
### 없으면 만들고 있으면 넘어가라는 말임
### 그리고 storageattatch해서 스토리지를 연결해주는 것임

이런 구성을 하면

이런식으로 10G짜리 디스크가 할당되는 것임

vagrant snapshot save before-rook		#혹시 모르니 snapshot을 찍어둬도 좋음
vagrant up

https://ceph.io/en/

ceph는 스토리지고 스토리지를 쿠버네티스에 맞게 설치해주는 것이 rook임

전통적으로는 스토리지를 사게되면 Block File object를 따로.. 사게됨
근데 ceph는 하나의 관리자로 file block object스토리지를 관리하게됨

knode1으로 ssh 접속을 하고..
ansible all -i ~/kubespray/inventory/mycluster/inventory.ini -m command -a 'sudo lsblk'

https://rook.io/docs/rook/latest/Getting-Started/quickstart/

https://github.com/rook/rook

git clone --single-branch --branch v1.9.3 https://github.com/rook/rook.git
cd rook/deploy/examlples
ls
kubectl create -f crds.yaml -f common.yaml -f operater.yaml
kubectl get ns
kubectl get po rook-ceph

### 이게 running상태로 완료가 되어야함


rook-ceph-operator는 설치를 위한것이지 rook-ceph가 아님

cluster를 설치 할껀데.. 종류가 많다

kubectl create -f cluster.yaml

### operater에 의해서 pod들이 쭉쭉만들어짐

필수 구성은 이렇다



구성 실패..
다시 동적 프로비저닝을 해보면

https://kubernetes.io/ko/docs/concepts/storage/storage-classes/

spec이 없는 대표적인 구성임
실습은 나중에..


https://kubernetes.io/ko/docs/concepts/storage/storage-classes/

apiVersion apps/v1
kind: Deployment
metadata:
  name: myweb-deploy
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
    labels:
      app: web
    spec:
      containers:
        - name: myweb
          image: ghcr.io/c1t1d0s7/go-myweb
          ports:
            - containerPort: 8080
kubectl create -f myweb-deploy.yaml
kubectl get deploy
kubectl get rs
kubectl get po

Deploy가 RS을 만들고 RS가 Pod를 만듬

https://thenewstack.io/deployment-strategies/
어플리케이션의 배포 전략이라는 문서임
소프트웨어를 어떻게 배포할것인지에 대한 일반적인 전략

어플리케이션을 배포할 때 6가지 전략
이것은 쿠버네티스에서만 사용하는 전략은 아니고 일반적인 전략임

그중에서 우리는 Deployment에 대해서 사용할 예정


이 상태에서 2번째 버전을 어떻게 배포할것이냐에 대한 문제이다.

이렇게 하는 방식이 Recreate 전략이다.
다만 이 전략의 단점은 downtime이 발생한다는 것이다.

다음은 Rolling Update이다

하나 지우고 하나 생성하는 방식으로 변경을 한다.
이 전략의 장점은 무중단시스템이라는 것이다.
단점은 Rollout과 rollback에 시간이 좀 걸린다.
API는 기본적으로 V1과 V2를 지원할 수 있어야한다.

다음은 Blue/Green이다.
이거는 먼저 V2를 프로비저닝 해놓고

장점은 다운타임이 적지만
단점은 여유 리소스가 필요하다. 그래서 비용이 많이 든다.

다음은 Canary 배포이다.
카나리아라는 새가 있다.
유해 가스에 민감한 새를 미리 보내고 살아 돌아오면 안전하다라는 식이었음


일부 트래픽을 V2로 천천히 보내고 점점 V2로 모든 트래픽을 보낸다.
쿠버네티스는 이런 기능을 가지고 있지는 않다

다음은 A/B테스팅이다.

예를들어 pc에서 들어갈 때랑 스마트폰으로 들어갈 때랑의 차이를 생각해보면 된다.
즉, 특정 종류 일부만 테스트를 한다.

다음은 Shadow이다.
트래픽이 양쪽 다 전송됨 클라이언트는 구분하지 못함

다 좋지만
단점은 구현하기가 어렵다.

표로 정리해보면...


deployment 실습


go-myweb:v1을 go-myweb:v1.0으로 바꾸어주어야함

이 두 개 서비스를 만듬

apiVersion: v1
kind: Service
metadata:
  name: myweb-svc-lb
spec:
  type: LoadBalancer
  selector:
    app: web
  ports:
    - port: 80
      targetPort: 8080
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myweb-deploy
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
        - name: myweb
          image: ghcr.io/c1t1d0s7/go-myweb:v1.0
          ports:
            - containerPort: 8080

이렇게하고 둘 다 create해줌

### 한 쪽은

watch -n1 kubectl get deploy,rs,po

### 또 한 쪽은

watch -n1 curl 192.168.100.240
kubectl rollout
kubectl rollout status deploy myweb-deploy
kubectl rollout history deploy myweb-deploy

이미지를 교체하는 방법
replace
kubectl edit
apply
patch

kubectl set도 있음

kubectl set image deployments myweb-deploy myweb=ghcr.i
o/c1t1d0s7/go-myweb:v2.0 --record

### --record옵션을 붙이면 kubectl rollout history 했을 때 추적이 가능해진다.


kubectl rollout
kubectl rollout undo deploy myweb-deploy

1상태로 돌아가지만 버전은 1,2를 지나서 3

또 바꿀 수 있다

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myweb-deploy
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
        - name: myweb
          image: ghcr.io/c1t1d0s7/go-myweb:v2.0
          ports:
            - containerPort: 8080
kubectl replace -f myweb-deploy.yaml

이런식으로 하면 이미지를 무슨 이미지를 사용했는지 history에 남지 않기 때문에 다른 방식으로 해보겠다.
annotations를 추가하면 된다.

annotations:
    kubernetes.io/change-cause: "Change Go Myweb version from 3 to 4"
kubectl apply -f myweb-deploy.yaml


이런식으로 중간 과정을 확인할 수도 있다.

아직더 Deployment를 할 수 있음


최대 불가 최대 서지

https://kubernetes.io/ko/docs/concepts/workloads/controllers/deployment/#%EC%A0%84%EB%9E%B5

max surge와
max unavailable이 있는데
surge는 무언가 평소보다 튀는 값을 말함
Deployment가 있고 rollout을 할 때
max surge가 1이면 순간적으로 3+1해서 4개까지할 수 있다고 한다.
만들고 지운다는 개념으로 하면 최대 3개를 넘게되고
지우고만든다라는 개념으로 하게되면 최대 3개를 넘을 필요는 없어지게된다.

이런식으로 배포 전략을 짤 수 있다고 한다.


비율로 선언할 수 있고 값으로 선언할 수 있다 비율로 할 시에는 올림을 한다고 한다.


이런식으로 작성을 할 수 있다.

만약에 특정 버전의 세부정보를 확인하기 위해서는 이렇게 하면 된다.


이렇게 이미지 히스토리의 버전을 지정해서 돌아갈 수 있다.

minReadySeconds로 딜레이를 일부러 시킬 수 있다.

liveness나
startup probe를 사용한다면 필요하지 않을 수 있다.

revisionHistoryLimit

히스토리를 제한할 수도 있다고 한다.

데몬셋에서도 updateStrategy가 있다.

역시 데몬셋 updateStrategy에도 maxUnavailable이 있다.

stateless한 구성은 전부 이런 디플로이먼트로 한다고 한다..


NFS

https://kubernetes.io/ko/docs/concepts/storage/storage-classes/#%ED%94%84%EB%A1%9C%EB%B9%84%EC%A0%80%EB%84%88

https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner

sudo systemctl restart nfs-fernel-server
sudo mkdir /nfsvolume
sudo rm -f #안에 파일이 있다면 다 지워줌
git clone https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner.git
ls
cd nfs-subdir[tab]
ls
cd deploy
ls


vi deployment.yaml



### 생성

kubectl create -f deployment.yaml
kubectl create -f class.yaml
### 확인

kubectl get deploy,rs,po
kubectl get sc
cd yaml/volume/nfs
ls
cd ..
cd -r nfs nfs-dynamic
cd nfs-dynamic
ls
rm mypv.yaml

### 그리고 이미 생성되었던 서비스들 delete

vi mvpvc.yaml

kubectl get sc


이렇게 pvc만 만들어도 pvclass에 의해서 자동으로 만들어지는 것을 볼 수 있다.

sudo ls -l /nfsvolume

kubectl create -f mypvc-dynamic.yaml -f myweb-rs.yaml -f myweb-svc-lb.yaml

결과 확인

삭제

kubectl delete -f .

kubectl get pv,pvc
kubectl get dc
pvc를 지우면 pv가 같이 지워지는 것을 확인할 수 있다.

cd ~/nfs-subdir-external-provisioner

vi class.yaml

annotations:
    storageclass.kubernetes.io/is-default-class: "true"


이 부분이 달라졌다고 함


이렇게 다른점 확인

이름 뒤에 default가 붙는 것을 default 스토리지 클래스라고 한다.


ConfigMap & Secret

mkdir env
cd env
vi myweb.yaml
apiVersion: v1
kind: Pod
metadata:
  name: myweb-env
spec:
  containers:
    - name: myweb
      image: ghcr.io/c1t1d0s7/go-myweb:alpine
      env:
        - name: MESSAGE
          value: "Customized Hello World"
kubectl create -f myweb.yaml
kubectl get po
kubectl exec -it myweb-env -- sh

이렇게 환경변수를 제공할 수 있다는 것을 기억하길 바람..

kubectl delete -f .

ConfigMap

cd ~
mkdir cm
cd cm
kubectl api-resources | grep configmap
kubectl explain cm.spec
kubectl explain cm
kubectl explain cm.data

https://kubernetes.io/ko/docs/concepts/configuration/configmap/

사용 용도:

  • 환경 변수
  • 볼륨/파일
    • 설정파일
    • 암호화 키/인증서

사용동기도 한 번 읽어보는 것을 추천함

vi myconfig.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: mymessage
data:
  MESSAGE: Customized Hello ConfigMap
kubectl create -f mymessage.yaml
kubectl get cm
kubectl describe cm mymessage


configmap의 이름을 설정할 수 있다고 함..

apiVersion: v1
kind: Pod
metadata:
  name: myweb-env
spec:
  containers:
    - name: myweb
      image: ghcr.io/c1t1d0s7/go-myweb:alpine
      envFrom:
        - configMapRef:
            name: mymessage
kubectl create -f myweb.yalm
kubectl exec -it myweb-env -- sh


이렇게 키 값 형태로 환경변수를 설정할 수 있다.

kubectl explain pods.spec.volumes.configMap

### 볼륨으로 지정하는게 가능하다

apiVersion: v1
kind: Pod
metadata:
  name: myweb-cm-vol
spec:
  containers:
    - name: myweb
      image: ghcr.io/c1t1d0s7/go-myweb:alpine
      volumeMounts:
        - name: cmvol
          mountPath: /myvol

  volumes:
    - name: cmvol
      configMap:
        name: mymessage
kubectl create....
kubectl exec -it myweb-cm-vol -- sh
ls
cd /myvol/
ls
ls -l
cat MESSAGE
### 키가 file명 데이터가 value

이런 것도 있다


1번은 모두를 등록
2번은 특정 키 값만 등록


Secret

기본적인 원리는 똑같다 key value를 제공하기 때문임
다만 다른점은 value를 base64로 인코딩을 함
중요한거는 base64는 암호화가 아님
물론 AWS의 KMS를 이용하거나
Hashicop의 Vault를 이용하면 암호화가 가능하긴하다.

cd ~
mkdir secret
cd secret
kubectl api-resources | secret
kubectl explain secret.type


value의 종류를 지정해줄 수 있다.
dockercfg
dockerconfigjson은 docker login할 때 그 인증임
이걸 이용해서 registry를 이용할 수 있는것임

vi mydata.yaml
apiVersion: v1
kind: Secret
metadata:
  name: mydata
type: Opaque
data:
  id: admin
  pwd: P@ssw0rd

kubectl create -f mydata.yaml
하면 오류가남

base64
admin



이런식으로 인코딩해서 값을 집어넣어준다.

apiVersion: v1
kind: Secret
metadata:
  name: mydata
type: Opaque
data:
  id: YWRtaW4K
  pwd: UEBzc3cwcmQK
kubectl create -f mydata.yaml
kubectl get secret
kubectl describe secret mydata


이렇게 데이터 크기만 보여줌
다만

kubectl get secret mydata -o yaml

### 하면 보이긴함 근데 인코딩은 암호화된게 아니기때문에 주의해야함

Pod를 생성할 때 Secret은 이걸 설정해주면됨



kubectl explain pod.spec.volumes.secret

### secret name이 있다

키는 파일명 value는 ..

다음은 nginx로 https를 하는 방법을 해볼 예정임


Nginx HTTPs 서버

아파치는 너무 무겁고 설정할게 너무 많아서 nginx가 점점 많아지고 있는 추세라고 하심

cat conf/nginx-tls.conf
server {
    listen              80;
    listen              443 ssl;
    server_name         myapp.example.com;
    ssl_certificate     /etc/nginx/ssl/tls.crt;
    ssl_certificate_key /etc/nginx/ssl/tls.key;
    ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers         HIGH:!aNULL:!MD5;
    location / {
        root   /usr/share/nginx/html;
        index  index.html;
    }
}

kubectl run nginx --image nginx
kubectl exec -it nginx -- bash
cd /usr/share/nginx/html/
ls
cd ~
cd /etc/nginx
ls
cd conf.d/
ls					#여기에 추가적인 설정파일들이 들어갈 에정임
					#파일명은 상관이 없고 conf로 끝나면 된다.
kubectl delete ... #아까 만든 Pod삭제


이렇게 https가 되는 것임

이걸 config로해서 어디에 제공해야하는지 고민해보아라
미니 과제

ls cd x509


이런것도 있지만 중요한 것은 Domain이 있어야 사용 가능하다.

지금은 간단하게 테스트하기위해
self signed certificate
ssc
를 사용할 예정

openssl genrsa -out nginx-tls.key 2048			#private키를 만들어준다. out 파일명 지정 키길이를 지정해줄 수 있음
ls
openssl rsa -in nginx-tls.key -pubout -out nginx-tls				# 퍼블릭 키를 만들어줌
ls
openssl req -new -key nginx-tls.key -out nginx-tls.csr		#Certificate Signing Request를 의미함 서명 요청 인증서

### 이 파일을 Letsencript같은 곳으로 보낼 수 있다.
### 다만 이 무료는 3개월마다 바꾸어주어야
### gabia에서 ssl호스팅을 가보면 

ls
### nginx-tls.csr 파일을 만들어줌
openssl req -x509 -days 3650 -key nginx-tls.key -in nginx-tls.csr -out nginx-tls.crt
ls

실제로는 서명된 파일을 줌
필요 없는 파일은 지워줌


이렇게 2개만 있으면 됨

이제 중요한 것은

인증서는 secret으로 등록


이것을 이용할것임


이런 구성이 기본 구성임

Pod를 만들것임
서비스 포트포워딩 등등..
curl 했을 때
curl https://192.168.100.240
자체서명 인증서는 오류가 나기 떄문에

이걸로 확인해야함
curl -k https://x.x.x.x
했을 때 컨텐츠가 나와야함

configmap과
secret을 파일로 제공해서
해결을 해보시오..

성공창..


CA가 없어서 올바르지 않은것임


이렇게말고

이렇게해서 한 줄로 넣기

kubectl get cm
kubectl describe cm nginx-tls-config
kubectl get secret
kubectl describe secret nginx-tls-secret
kubectl get po
kubectl get po describe 로 확인...
kubectl svc,ep,po,cm,secret


다음시간에는
Ingress + Secret = TLS Termination
을 해볼 것이고
StatefullSet을 해볼것임
이를 위해 Headless SVC와 Dynamic Provisioning을 사용할 것임

그리고 Scheduling

Horizontal Pod Autoscaler

RBAC


Helm
Package
Elastic Stack(Log)
Prometeus(Monitoring)


EKS

이렇게하면 쿠버네티스는 어느정도 끝이 남..

0개의 댓글