728x90

Markup Language


마크업 언어란

마크업 언어란

  • 태그 등을 이용하여 문서나 데이터의 구조를 명기하는 언어 중 하나
  • 태그는 용도가 점차 확장되어 문서의 구조를 표현하는 역할을 하게 됨

 

마크업 언어의 종류

  • 표현적 마크업 - 전통적인 워드 처리 시스템이 사용하는 마크업
  • 절차적 마크업 - 텍스트에 포함되며 문자를 처리할 프로그램 명령 제공
  • 기술적 마크업 - 문서의 일부에 레이블을 만듦

 

마크업 언어의 특징

  • 마크업 언어의 공통된 특징은 문서의 텍스트와 동일한 데이터 스트림 또는 파일의 마크업 지침을 혼합함

 


 

Markdown


마크다운 사용

1. 제목

  • #
# 1. 제목

# 제목1
## 제목2
### 제목3
#### 제목4
##### 제목5
###### 제목6


제목1
===

제목2
---

---

 

2. 단락/줄바꿈

  • 엔터
# 2. 단락/줄바꿈

안녕하세요

반갑습니다

 

3.  강조

  • * 또는 _
# 3. 강조

안녕하세요 *jin* 입니다.

안녕하세요 **jin** 입니다.

안녕하세요 ***jin*** 입니다.

안녕하세요 _jin_ 입니다.

안녕하세요 __jin__ 입니다.

안녕하세요 ___jin___ 입니다.

안녕하세요 *_jin_* 입니다.

안녕하세요 *__jin__* 입니다.

안녕하세요 _*jin*_ 입니다.

안녕하세요 __*jin*__ 입니다.

 

4. 인용문

  • >
# 4. 인용문

> 순다피차이: 메롱

> https://google.com

> 참고
> > 철수: 안녕!
> > 영희: 반가워~

 

5. 목록

  • - 또는 * 또는 숫자
# 5. 목록

- 목록1
- 목록2
- 목록3
  - 하위 목록1
  - 하위 목록2

* 목록1
* 목록2

* 목록1
  - 하위 목록1
    + 하하위 목록1

- 목록1
* 목록2
+ 목록3

1. 목록1
2. 목록2
   1. 하위 목록1
      - 하하위 목록1

 

6. 코드 블록

  • `
# 6. 코드 블록

`import packages`

서비스를 확인하는 명령은 `systemctl status ssh` 입니다.

```python
a = 100
b = 100
c = a + b
print(c)
```

 

7. 링크

  • [링크를 지정할 이름](링크)
# 7. 링크

https://kubernetes.io

[쿠버네티스 공식 사이트](https://kubernetes.io)

[쿠버네티스 공식 사이트](https://kubernetes.io)에서 내용을 참조하세요

 

8. 이미지

  • ![]()
# 8. 이미지
![tmux image](https://upload.wikimedia.org/wikipedia/commons/thumb/3/35/Tux.svg/202px-Tux.svg.png)

![image](file:///a/b/c/.jpg)

 

9. 테이블

  • 기본 좌측 정렬이며, : (콜론)을 사용하여 정렬 지정
# 9. 테이블 (기본 좌측 정렬)
|번호|이름|갯수|
|-|-|-|
|1|사과|100|
|2|배|2000|
|3|딸기|3000|

|번호|이름|갯수|
|-:|:-:|:-|
|1|사과|100|
|2|배|2000|
|3|딸기|3000|

 

10. 취소선

  • ~~
# 10. 취소선

현재 버전은 ~~1.0.1~~ 입니다.

 

11. 작업 목록

  • - [ ]
# 11. 작업 목록

- [ ]  todo 1
- [ ]  todo 2
- [X]  todo 3

 

 

728x90
728x90

Git 시작하기


버전 관리

버전 관리란

  • 참고 링크
  • 버전 관리 시스템은 파일 변화를 시간에 따라 기록했다가 나중에 특정 시점의 버전을 다시 꺼내올 수 있는 시스템
  • 버전 관리 시스템: Version Control System

 

 

로컬 버전 관리(VCS)

  • Patch Set을 관리함
  • Patch Set이란 파일에서 변경되는 부분을 말함
  • 모든 파일을 특정 시점으로 되돌릴 수 있음

 

 

 

 중앙 집중식 버전 관리(CVCS)

  • 파일을 관리하는 서버가 별도로 존재함
  • 중앙 서버에서 파일을 받아서 사용하는 방식
  • 중앙 서버에서 문제가 발생한다면 아무 것도 할 수 없다는 치명적인 단점이 있음

 

 

 

분산 버전 관리 시스템(DVCS)

  • 서버와 클라이언트 모두가 동일한 데이터를 복제하여 가지고 있음
  • 중앙 집중식 관리 시스템의 단점을 보완함

 

 

728x90

'쿠버네티스 교육 > 강의 내용 정리' 카테고리의 다른 글

220706_1_Markup Language  (0) 2022.07.06
220704_1_젠킨스_vagrant를 이용한 젠킨스 설치  (0) 2022.07.04
220630_1_k8s_Secret  (0) 2022.06.30
220629_4_k8s_ConfigMap  (0) 2022.06.29
220628_4_k8s_볼륨_hostPath  (0) 2022.06.28
728x90

젠킨스 설치


젠킨스와 zsh 쉘 설치

젠킨스 설치

  • vagrant를 이용한 젠킨스 설치
vagrant up
# Vagrantfile
# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|
  # jenkins
  config.vm.define "jenkins" do |config|
    config.vm.box = "ubuntu/focal64"
    config.vm.provider "virtualbox" do |vb|
      vb.name = "jenkins"
      vb.cpus = 2
      vb.memory = 3000
    end
    config.vm.hostname = "jenkins"
    config.vm.network "private_network", ip: "192.168.57.10", nic_type: "virtio"
  end

  # Enable SSH Password Authentication
  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

 

  • 젠킨스 접속
vagrant ssh jenkins

 

  • 데비안 계열 OS 패키지 목록 가져오기 => 추후 패키지 다운로드 시 오류 발생 방지
sudo apt update

 

zsh 쉘 설치 및 환경 설정

  • CMD 또는 Powershell 사용은 권장하지 않음
  • Windows Terminal 사용을 권장
  • zsh 쉘 설치
$ sudo apt install zsh

$ which zsh
/usr/bin/zsh

 

  • zsh 쉘 프레임워크 설치
$ sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"

 

 

GitHub - romkatv/powerlevel10k: A Zsh theme

A Zsh theme. Contribute to romkatv/powerlevel10k development by creating an account on GitHub.

github.com

# 윈도우 터미널을 열고 'ctrl + shfit + ,'를 눌러 settings.json 파일 수정
"profiles": 
    {
         "defaults": 
        {
            "closeOnExit": "always",
            "colorScheme": "Tango Dark",
            "fontFace": "MesloLGS NF",
            "fontSize": 12
        },

 

  • git 설치
git clone --depth=1 https://github.com/romkatv/powerlevel10k.git ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/powerlevel10k

git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting

git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions

 

  • 테마 변경 및 플러그인 추가
vi ~/.zshrc
 
 11 ZSH_THEME="powerlevel10k/powerlevel10k"
 
 80 plugins=(git
 81          zsh-syntax-highlighting
 82          zsh-autosuggestions)
 83

 

  • 변경 사항 적용
  • 윈도우 터미널의 폰트와 테마가 변경된 것을 확인할 수 있음
exec zsh

# zsh 쉘 UI 설정
p10k configure

테마 및 플러그인 적용

 

테마 재설정

728x90

'쿠버네티스 교육 > 강의 내용 정리' 카테고리의 다른 글

220706_1_Markup Language  (0) 2022.07.06
220704_2_젠킨스_Git 시작하기  (0) 2022.07.04
220630_1_k8s_Secret  (0) 2022.06.30
220629_4_k8s_ConfigMap  (0) 2022.06.29
220628_4_k8s_볼륨_hostPath  (0) 2022.06.28
728x90

Secret


시크릿이란

민감한 정보들을 저장하는 용도

  • 쿠버네티스 내부에서 보안이 필요한 설정들을 구성할 때 사용
  • configMap과 같은 key-value 저장소
  • 패스워드, 암호화 키/인증서, 토큰 등 소량의 민감한 데이터 저장
  • BASE64로 인코딩하여 데이터 저장
  • 컨피그 맵은 단순 데이터나 민감하지 않은 설정 데이터를 저장하고 참조하는 용도
  • 개별 오브젝트당 1MiB로 제한

 

시크릿 저장 데이터 종류

시크릿에 직접 저장 가능 generic key-value 형식의 임의의 데이터
docker-registry 도커 저장소 인증 정보
tls TLS 키 및 인증서
시크릿에 직접 저장 불가능 service-account-token 서비스 계정 토큰

 

시크릿 생성 방법

  • 직접 명령
kubectl create secret <TYPE> <NAME> [OPTIONS]

 

  • 일반 시크릿
kubectl create secret generic <NAME> [--from-file=[key=]source] [--from-literal=key1=value1]

 

  • 도커 저장소 인증 정보용 시크릿
kubectl create secret docker-registry <NAME> \
--docker-username=user --docker-password=password \
--docker-email=email [--docker-server=string]

 

  • TLS 키/인증서용 시크릿
kubectl create secrets tls <NAME> --cert=cert-file --key=key-file

 


 

실습 - 1

명령으로 Secret 생성

  • secret 디렉토리 생성
vagrant@kube-master1:~
$ mkdir secret
vagrant@kube-master1:~
$ cd secret/

 

 

  • secret에 저장할 파일 생성
  • id.txt 파일과 pwd.txt 파일을 secret 디렉토리에 생성
vagrant@kube-master1:~/secret
$ echo -n "admin" > id.txt
vagrant@kube-master1:~/secret
$ echo -n "P@ssw0rd" > pwd.txt
vagrant@kube-master1:~/secret
$ cat id.txt
adminvagrant@kube-master1:~/secret
$ cat pwd.txt
P@ssw0rdvagrant@kube-master1:~/secret

 

  • id.txt 파일과 pwd.txt 파일을 이용하여 secret 생성
$ kubectl create secret generic my-secret --from-file=id.txt --from-file=pwd.txt
secret/my-secret created
vagrant@kube-master1:~/secret
$ kubectl get secrets
NAME                  TYPE                                  DATA   AGE
default-token-wl2vl   kubernetes.io/service-account-token   3      9d
my-secret             Opaque                                2      5s

 

 

  • 생성한 secret 정보 확인
  • kubectl get
  • kubectl describe
  • 시크릿 생성 시 자동으로 필드 값을 base64로 인코딩 처리함 (.data 필드에서 확인 가능)
$ kubectl get secret my-secret -o yaml
apiVersion: v1
data:
  id.txt: YWRtaW4=
  pwd.txt: UEBzc3cwcmQ=
kind: Secret
metadata:
  creationTimestamp: "2022-06-30T03:36:13Z"
  managedFields:
  - apiVersion: v1
    fieldsType: FieldsV1
    fieldsV1:
      f:data:
        .: {}
        f:id.txt: {}
        f:pwd.txt: {}
      f:type: {}
    manager: kubectl
    operation: Update
    time: "2022-06-30T03:36:13Z"
  name: my-secret
  namespace: default
  resourceVersion: "770149"
  selfLink: /api/v1/namespaces/default/secrets/my-secret
  uid: beb61678-e579-4d14-ba06-365f8f263159
type: Opaque

 

$ kubectl describe secret my-secret
Name:         my-secret
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  Opaque

Data
====
id.txt:   5 bytes
pwd.txt:  8 bytes

 

  • 암호 디코딩
vagrant@kube-master1:~/secret
$ echo "YWRtaW4=" | base64 --decode
admin

vagrant@kube-master1:~/secret
$ echo "UEBzc3cwcmQ=" | base64 --decode
P@ssw0rd

 

  • 디폴트 시크릿 확인
$ kubectl get secrets
NAME                  TYPE                                  DATA   AGE
default-token-wl2vl   kubernetes.io/service-account-token   3      9d
my-secret             Opaque                                2      7m15s

$ kubectl describe secrets default-token-wl2vl
Name:         default-token-wl2vl
Namespace:    default
Labels:       <none>
Annotations:  kubernetes.io/service-account.name: default
              kubernetes.io/service-account.uid: c768f156-ad53-4038-bdb8-d7465bc4724d

Type:  kubernetes.io/service-account-token

Data
====
ca.crt:     1025 bytes
namespace:  7 bytes
token:      eyJhbGciOiJSUzI1NiIsImtpZCI6IjZIWG9vU05yZF95VXo4bWVfR3Z2eV95THFRa0JFT2ZkRFZrODlqLWdLWXcifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImRlZmF1bHQtdG9rZW4td2wydmwiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGVmYXVsdCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6ImM3NjhmMTU2LWFkNTMtNDAzOC1iZGI4LWQ3NDY1YmM0NzI0ZCIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmRlZmF1bHQifQ.rc6nzgKEUMID5BCoLlu_vhwPSPOSj0Dp30-0dVW1hiM6GKtrqhUVdXNHeFVFTcNzURNHtYZfuLEogsNAJJ9-iePOCdnNRmjnG4bdIQlhNpJJj7A8fF2jYPD_W5S7ir09eVHEZgcrNcRQLpuLnzsvalr_LrW_xNvBY--MB7W2jnV0iyiAslaOL8-KLSqLTh9yuJsg6CXEDLslHnLAvH_72f0ESM-CHKIxXbJ7_fLchvM8J0iSQAYvq5wc3yzaC1l2ZkpNQjphCSED7aoHvcpHbWWCM6MS6R04gTSYrctSEW8DBxHyVyhH_sNUYs9KXge0UQqo9OdAEHncptlcMOHZqQ

 

  • 실행 중인 파드에 적용된 디폴트 시크릿 확인
$ kubectl describe pod nginx-pod-compress
~
Volumes:
  nginx-compress-config:
    Type:      ConfigMap (a volume populated by a ConfigMap)
    Name:      nginx-gzip-config
    Optional:  false
  default-token-wl2vl:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-wl2vl
    Optional:    false
~

 


 

실습 - 2

Secret을 이용한 Nginx https 웹 서비스

  • 인증서 생성
vagrant@kube-master1:~/secret/nginx-tls
$ openssl req -x509 -nodes -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=myapp.exampl
e.com"
Can't load /home/vagrant/.rnd into RNG
140097390891456:error:2406F079:random number generator:RAND_load_file:Cannot open file:../crypto/rand/randfile.c:88:Filename=/home/vagrant/.rnd
Generating a RSA private key
.................+++++
.................................+++++
writing new private key to 'tls.key'
-----
vagrant@kube-master1:~/secret/nginx-tls
$ ls
tls.crt  tls.key

 

  • HTTPS 인증서를 저장하는 용도로 secret 생성
vagrant@kube-master1:~/secret/nginx-tls
$ kubectl create secret tls nginx-tls-secret --cert=tls.crt --key=tls.key
secret/nginx-tls-secret created

vagrant@kube-master1:~/secret/nginx-tls
$ kubectl get secrets
NAME                  TYPE                                  DATA   AGE
default-token-wl2vl   kubernetes.io/service-account-token   3      9d
my-secret             Opaque                                2      151m
nginx-tls-secret      kubernetes.io/tls                     2      7s

 

  • 생성한 secret 정보 확인 (yaml 또는 json 형식으로 확인)
vagrant@kube-master1:~/secret/nginx-tls
$ kubectl get secrets nginx-tls-secret -o yaml

$ kubectl get secrets nginx-tls-secret -o json

 

 

  • secret 정보 자세히 확인
vagrant@kube-master1:~/secret/nginx-tls
$ kubectl describe secrets nginx-tls-secret
Name:         nginx-tls-secret
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  kubernetes.io/tls

Data
====
tls.crt:  1135 bytes
tls.key:  1704 bytes

 

  • nginx conf 구성 파일 생성
vagrant@kube-master1:~/secret/nginx-tls
$ vi ../nginx-tls.conf

vagrant@kube-master1:~/secret/nginx-tls
$ cat ../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.2 TLSv1.3;
    ssl_ciphers         HIGH:!aNULL:!MD5;
    location / {
        root   /usr/share/nginx/html;
        index  index.html;
    }
}

 

  • nginx conf 구성 파일을 이용하여 configmap 생성
vagrant@kube-master1:~/secret/nginx-tls
$ kubectl create configmap nginx-tls-config --from-file=../nginx-tls.conf
configmap/nginx-tls-config created

vagrant@kube-master1:~/secret/nginx-tls
$ kubectl get cm
NAME               DATA   AGE
nginx-tls-config   1      4s

vagrant@kube-master1:~/secret/nginx-tls
$ kubectl describe configmap nginx-tls-config
Name:         nginx-tls-config
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
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.2 TLSv1.3;
    ssl_ciphers         HIGH:!aNULL:!MD5;
    location / {
        root   /usr/share/nginx/html;
        index  index.html;
    }
}

Events:  <none>

 

  • nginx 파드 생성
vagrant@kube-master1:~/secret
$ cat nginx-pod-https.yml
apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod-https
spec:
  containers:
  - name: nginx-https
    image: nginx
    volumeMounts:
    - name: nginx-tls-config
      mountPath: /etc/nginx/conf.d
    - name: https-cert
      mountPath: /etc/nginx/ssl
      readOnly: true
    ports:
    - containerPort: 80
      protocol: TCP
    - containerPort: 443
      protocol: TCP
  volumes:
  - name: nginx-tls-config
    configMap:
      name: nginx-tls-config
  - name: https-cert
    secret:
      secretName: nginx-tls-secret
      
vagrant@kube-master1:~/secret
$ kubectl create -f nginx-pod-https.yml
pod/nginx-pod-https created

vagrant@kube-master1:~/secret
$ kubectl get po
NAME              READY   STATUS    RESTARTS   AGE
nginx-pod-https   1/1     Running   0          7s

 

 

서비스 확인

  • 8443 포트 사용 여부 확인 후 포트 포워딩 설정
vagrant@kube-master1:~/secret
$ netstat -anpt | grep :8443
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
tcp        0      0 10.0.2.15:56940         10.233.89.41:8443       TIME_WAIT   -

vagrant@kube-master1:~/secret
$ kubectl port-forward nginx-pod-https 8443:443
Forwarding from 127.0.0.1:8443 -> 443
Forwarding from [::1]:8443 -> 443

 

  • 새 터미널에서 실행
  • 인증서 적용이 정상적으로 됨
vagrant@kube-master1:~
$ curl https://localhost:8443 -k -v
* Rebuilt URL to: https://localhost:8443/
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS Unknown, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Unknown (8):
* TLSv1.3 (IN), TLS Unknown, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS Unknown, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS Unknown, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Client hello (1):
* TLSv1.3 (OUT), TLS Unknown, Certificate Status (22):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use http/1.1
* Server certificate:
*  subject: CN=myapp.example.com
*  start date: Jun 30 06:04:55 2022 GMT
*  expire date: Jul 30 06:04:55 2022 GMT
*  issuer: CN=myapp.example.com
*  SSL certificate verify result: self signed certificate (18), continuing anyway.
* TLSv1.3 (OUT), TLS Unknown, Unknown (23):
> GET / HTTP/1.1
> Host: localhost:8443
> User-Agent: curl/7.58.0
> Accept: */*
>
* TLSv1.3 (IN), TLS Unknown, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS Unknown, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS Unknown, Unknown (23):
< HTTP/1.1 200 OK
< Server: nginx/1.23.0
< Date: Thu, 30 Jun 2022 06:19:48 GMT
< Content-Type: text/html
< Content-Length: 615
< Last-Modified: Tue, 21 Jun 2022 14:25:37 GMT
< Connection: keep-alive
< ETag: "62b1d4e1-267"
< Accept-Ranges: bytes
<
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
* Connection #0 to host localhost left intact

 

참고

  • 에러 발생 시 이벤트, 로그 확인
# 이벤트 확인
kubectl describe pod nginx-pod-https

# 어플리케이션 error 확인
kubectl log ngnix-pod-https

 

  • 인증서 생성 시 에러 발생
  • Can't load /home/vagrant/.rnd into RNG
$ openssl req -x509 -nodes -newkey rsa:2048 -keyout tls.key -out tls.crt -days 365
-subj "/CN=myapp.example.com"
Can't load /home/vagrant/.rnd into RNG
139993021399488:error:2406F079:random number generator:RAND_load_file:Cannot open file:../crypto/rand/randfile.c:88:Filename=/home/vagrant/.rnd

 

  • 해결
$ cd ~/; openssl rand -writerand .rnd

 


 

실습 - 3

TLS 종료 프록시 (Termination Proxy)

  • 노드 포트 서비스 생성 파일
vagrant@kube-master1:~/secret
$ cat myapp-svc-np.yml
apiVersion: v1
kind: Service
metadata:
  name: myapp-svc-np
spec:
  type: NodePort
  ports:
  - port: 80
    targetPort: 8080
    nodePort: 31111
  selector:
    app: myapp-rs

 

  • 레플리카셋 생성 파일
$ cat myapp-rs.yml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: myapp-rs
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp-rs
  template:
    metadata:
      labels:
        app: myapp-rs
    spec:
      containers:
      - name: myapp
        image: ghcr.io/c1t1d0s7/go-myweb:alpine
        ports:
        - containerPort: 8080

 

  • 서비스, 레플리카셋 생성
vagrant@kube-master1:~/secret
$ kubectl create -f myapp-rs.yml -f myapp-svc-np.yml
replicaset.apps/myapp-rs created
service/myapp-svc-np created

 

 

  • 인증서 생성
vagrant@kube-master1:~/secret/ingress-tls
$ openssl req -x509 -nodes -newkey rsa:2048 -keyout tls.key -out tls.crt -days 365 -subj "/CN=myapp.example.com"
Generating a RSA private key
....................................................+++++
........................+++++
writing new private key to 'tls.key'
-----

 

  • 시크릿 생성
  • crt, key 저장
vagrant@kube-master1:~/secret/ingress-tls
$ kubectl create secret tls ingress-tls-secret --cert=tls.crt --key=tls.key
secret/ingress-tls-secret created

 

  • 생성한 시크릿 확인
vagrant@kube-master1:~/secret/ingress-tls
$ kubectl get secrets
NAME                  TYPE                                  DATA   AGE
default-token-wl2vl   kubernetes.io/service-account-token   3      10d
ingress-tls-secret    kubernetes.io/tls                     2      9s

 

  • 인그레스 컨트롤러 생성 파일
vagrant@kube-master1:~/secret
$ cat myapp-ing-tls-term.yml
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: myapp-ing-tls-term
spec:
  tls:
  - hosts:
    - myapp.example.com
    secretName: ingress-tls-secret
  rules:
  - host: myapp.example.com
    http:
      paths:
      - path: /
        backend:
          serviceName: myapp-svc-np
          servicePort: 80

 

  • 인그레스 컨트롤러 생성
vagrant@kube-master1:~/secret
$ kubectl create -f myapp-ing-tls-term.yml
ingress.networking.k8s.io/myapp-ing-tls-term created
vagrant@kube-master1:~/secret
$ kubectl describe ingress myapp-ing-tls-term
Name:             myapp-ing-tls-term
Namespace:        default
Address:          192.168.56.21,192.168.56.22,192.168.56.23
Default backend:  default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
TLS:
  ingress-tls-secret terminates myapp.example.com
Rules:
  Host               Path  Backends
  ----               ----  --------
  myapp.example.com
                     /   myapp-svc-np:80 (10.233.101.113:8080,10.233.103.79:8080,10.233.76.161:8080)
Annotations:         <none>
Events:
  Type    Reason  Age    From                      Message
  ----    ------  ----   ----                      -------
  Normal  CREATE  5m39s  nginx-ingress-controller  Ingress default/myapp-ing-tls-term
  Normal  CREATE  5m39s  nginx-ingress-controller  Ingress default/myapp-ing-tls-term
  Normal  CREATE  5m39s  nginx-ingress-controller  Ingress default/myapp-ing-tls-term
  Normal  UPDATE  5m27s  nginx-ingress-controller  Ingress default/myapp-ing-tls-term
  Normal  UPDATE  5m27s  nginx-ingress-controller  Ingress default/myapp-ing-tls-term
  Normal  UPDATE  5m27s  nginx-ingress-controller  Ingress default/myapp-ing-tls-term
vagrant@kube-master1:~/secret
$ kubectl get po,svc,secret,ingress
NAME                  READY   STATUS    RESTARTS   AGE
pod/myapp-rs-4vcvd    1/1     Running   0          106m
pod/myapp-rs-9spff    1/1     Running   0          106m
pod/myapp-rs-hxzdf    1/1     Running   0          106m
pod/nginx-pod-https   1/1     Running   0          162m

NAME                   TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
service/kubernetes     ClusterIP   10.233.0.1     <none>        443/TCP        5d22h
service/myapp-svc-np   NodePort    10.233.3.139   <none>        80:31111/TCP   106m

NAME                         TYPE                                  DATA   AGE
secret/default-token-wl2vl   kubernetes.io/service-account-token   3      10d
secret/ingress-tls-secret    kubernetes.io/tls                     2      8m12s

NAME                                    CLASS    HOSTS                               ADDRESS                                     PORTS     AGE
ingress.extensions/myapp-ing            <none>   www.192-168-56-21.nip.io            192.168.56.21,192.168.56.22,192.168.56.23   80        3d2h
ingress.extensions/myapp-ing-mpath      <none>   web1.example.com,web2.example.com   192.168.56.21,192.168.56.22,192.168.56.23   80        3d1h
ingress.extensions/myapp-ing-tls-term   <none>   myapp.example.com                   192.168.56.21,192.168.56.22,192.168.56.23   80, 443   6m44s

 

서비스 확인

  • curl --resolve
vagrant@kube-master1:~/secret
$ curl --resolve myapp.example.com:443:192.168.56.21 -k -v https://myapp.example.com
* Added myapp.example.com:443:192.168.56.21 to DNS cache
* Rebuilt URL to: https://myapp.example.com/
* Hostname myapp.example.com was found in DNS cache
*   Trying 192.168.56.21...
* TCP_NODELAY set
* Connected to myapp.example.com (192.168.56.21) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS Unknown, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Unknown (8):
* TLSv1.3 (IN), TLS Unknown, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS Unknown, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS Unknown, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Client hello (1):
* TLSv1.3 (OUT), TLS Unknown, Certificate Status (22):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use h2
* Server certificate:
*  subject: CN=myapp.example.com
*  start date: Jun 30 08:45:52 2022 GMT
*  expire date: Jun 30 08:45:52 2023 GMT
*  issuer: CN=myapp.example.com
*  SSL certificate verify result: self signed certificate (18), continuing anyway.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* TLSv1.3 (OUT), TLS Unknown, Unknown (23):
* TLSv1.3 (OUT), TLS Unknown, Unknown (23):
* TLSv1.3 (OUT), TLS Unknown, Unknown (23):
* Using Stream ID: 1 (easy handle 0x5641f3eb8620)
* TLSv1.3 (OUT), TLS Unknown, Unknown (23):
> GET / HTTP/2
> Host: myapp.example.com
> User-Agent: curl/7.58.0
> Accept: */*
>
* TLSv1.3 (IN), TLS Unknown, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS Unknown, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS Unknown, Unknown (23):
* Connection state changed (MAX_CONCURRENT_STREAMS updated)!
* TLSv1.3 (OUT), TLS Unknown, Unknown (23):
* TLSv1.3 (IN), TLS Unknown, Unknown (23):
< HTTP/2 200
< server: nginx/1.19.2
< date: Thu, 30 Jun 2022 08:52:18 GMT
< content-type: text/plain; charset=utf-8
< content-length: 28
< strict-transport-security: max-age=15724800; includeSubDomains
<
Hello World!
myapp-rs-4vcvd
* TLSv1.3 (IN), TLS Unknown, Unknown (23):
* Connection #0 to host myapp.example.com left intact
728x90
728x90

ConfigMap

 


컨피그맵이란?

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

  • 별도의 데이터 저장을 위한 오브젝트
  • 같은 이미지를 이용해서 설정이 다른 컨테이너를 실행하기 위해 사용
  • 컨피그맵을 설정하고 파드(컨테이너)에서 그 값을 사용함 => 전체 또는 일부 값을 호출하여 사용
  • 환경 변수로 호출: 변수의 값으로 설정
  • volume 형태로 마운트: 파일

 


 

실습 - 1

env 변수로 어플리케이션에 변수 값 전달

  • env 변수가 정의된 파드 생성
$ cat myapp-pod-env.yml
apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod-env
spec:
  containers:
  - name: myapp
    image: ghcr.io/c1t1d0s7/go-myweb:alpine
    env:
    - name: MESSAGE
      value: "Customized Hello World!"
    ports:
    - containerPort: 8080
      protocol: TCP

 

  • 파드 생성
$ kubectl create -f myapp-pod-env.yml
pod/myapp-pod-env created

 

  • 8080 포트 사용 확인
$ netstat -antp | grep 8080
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
tcp        0      0 10.0.2.15:55440         10.233.89.39:8080       TIME_WAIT   -
tcp        0      0 10.0.2.15:47172         10.233.89.37:8080       TIME_WAIT   -
tcp        0      0 10.0.2.15:55024         10.233.89.39:8080       TIME_WAIT   -
tcp        0      0 10.0.2.15:55190         10.233.89.39:8080       TIME_WAIT   -
tcp        0      0 10.0.2.15:47088         10.233.89.37:8080       TIME_WAIT   -

 

  • myapp-pod-env 파드를 8080포트로 포트 포워딩
$ kubectl port-forward myapp-pod-env 8080:8080
Forwarding from 127.0.0.1:8080 -> 8080
Forwarding from [::1]:8080 -> 8080
Handling connection for 8080

 

실행 결과

  • 새 터미널을 열고 실행
  • env 변수로 전달되어 출력되는 것을 확인할 수 있음
vagrant@kube-master1:~
$ curl http://localhost:8080
Customized Hello World!
myapp-pod-env

 


 

실습 - 2

configMapRef: 컨피그맵 참조

  • 컨피그맵 설정 전체를 불러오는 파드 생성
$ cat myapp-pod-cm.yml
apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod-cm
spec:
  containers:
  - name: myapp
    image: ghcr.io/c1t1d0s7/go-myweb:alpine
    env:
    - name: MESSAGE
      valueFrom:
        configMapKeyRef:
          name: myapp-message
          key: message
    args:
    - $(MESSAGE)
    ports:
    - containerPort: 8080
      protocol: TCP

 

  • 참조할 message 파일 생성
$ cd ~
$ mkdir configmap
$ echo  "Customized Hello World!" > configmap/message

vagrant@kube-master1:~/configmap
$ ls
message  myapp-pod-cm.yml

 

  • myapp-message 컨피그맵 생성
vagrant@kube-master1:~/configmap
$ kubectl create configmap myapp-message --from-file=.
configmap/myapp-message created

vagrant@kube-master1:~/configmap
$ kubectl get configmap
NAME            DATA   AGE
myapp-message   3      23s

 

  • 파드 생성
$ kubectl create -f myapp-pod-cm.yml
pod/myapp-pod-cm created

vagrant@kube-master1:~/configmap
$ kubectl get pod
NAME           READY   STATUS    RESTARTS   AGE
myapp-pod-cm   1/1     Running   0          5s

 

  • 파드 포트포워딩
vagrant@kube-master1:~/configmap
$ kubectl port-forward myapp-pod-cm 8080:8080
Forwarding from 127.0.0.1:8080 -> 8080
Forwarding from [::1]:8080 -> 8080

 

 

실행 결과

  • 새 터미널에서 실행
vagrant@kube-master1:~
$ curl http://localhost:8080
Customized Hello World!

myapp-pod-cm

 


 

실습 - 3

컨테이너의 볼륨 형식으로 컨피그맵을 설정해 파일로 컨테이너에 제공

  • 마운트되면서 마운트 하기 전부터 존재했던 기존 파일에 접근이 안됨(사용할 수 없음) => 리눅스 특징: 파일 개별로 마운트 가능
  • 호스트에서 conf 디렉토리 생성
vagrant@kube-master1:~
$ mkdir conf/

vagrant@kube-master1:~
$ cd conf

 

  • config 파일 생성
$ cat conf/nginx-gzip.conf
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-config --from-file=nginx-gzip.conf
configmap/nginx-gzip-config created

 

  • 생성된 컨피그맵 정보 확인
$ kubectl get configmap
NAME                DATA   AGE
nginx-gzip-config   1      4s

$ kubectl describe configmap nginx-gzip-config
Name:         nginx-gzip-config
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
nginx-gzip.conf:
----
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;
    }
}

Events:  <none>

 

  • 파드 생성 파일
  • 볼륨이 .spec.containers.volumeMount.mountPath 필드로 마운트함
$ cat nginx-pod-compress.yml
apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod-compress
spec:
  containers:
  - name: nginx-compress
    image: nginx
    volumeMounts:
    - name: nginx-compress-config
      mountPath: /etc/nginx/conf.d
    ports:
    - containerPort: 80
      protocol: TCP
  volumes:
  - name: nginx-compress-config
    configMap:
      name: nginx-gzip-config

 

  • 파드 생성
$ kubectl create -f nginx-pod-compress.yml
pod/nginx-pod-compress created

 

  • 호스트에서 8080 포트를 사용하고 있는지 확인 => 10.0.2.15:8080이 있는지 확인
  • 현재 사용하고 있지 않으므로 8080으로 포트 포워딩 가능
$ netstat -natp | grep :8080
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
tcp        0      0 10.0.2.15:48024         10.233.89.40:8080       TIME_WAIT   -   
tcp        0      0 10.0.2.15:50058         10.233.89.42:8080       TIME_WAIT   -

 

  • 파드에 접속
$ kubectl port-forward nginx-pod-compress 8080:80
Forwarding from 127.0.0.1:8080 -> 80
Forwarding from [::1]:8080 -> 80

 

 

실행 결과

  • -v 옵션: 헤더 정보 확인
$ curl http://localhost:8080 -v
* Rebuilt URL to: http://localhost:8080/
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.58.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: nginx/1.23.0
< Date: Thu, 30 Jun 2022 02:41:04 GMT
< Content-Type: text/html
< Content-Length: 615
< Last-Modified: Tue, 21 Jun 2022 14:25:37 GMT
< Connection: keep-alive
< ETag: "62b1d4e1-267"
< Accept-Ranges: bytes
<
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

 

  • -H 옵션: 헤더 추가
$ curl -H "Accept-Encoding: gzip" http://localhost:8080 -v
* Rebuilt URL to: http://localhost:8080/
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.58.0
> Accept: */*
> Accept-Encoding: gzip
>
< HTTP/1.1 200 OK
< Server: nginx/1.23.0
< Date: Thu, 30 Jun 2022 02:45:28 GMT
< Content-Type: text/html
< Last-Modified: Tue, 21 Jun 2022 14:25:37 GMT
< Transfer-Encoding: chunked
< Connection: keep-alive
< ETag: W/"62b1d4e1-267"
< Content-Encoding: gzip
<
Warning: Binary output can mess up your terminal. Use "--output -" to tell
Warning: curl to output it to your terminal anyway, or consider "--output
Warning: <FILE>" to save to a file.
* Failed writing body (0 != 397)
* Failed writing data
* stopped the pause stream!
* Closing connection 0
728x90
728x90

hostPath


hostPath란

파드가 실행된 호스트의 파일이나 디렉토리를 파드에 마운트

  • 호스트에 있는 실제 파일이나 디렉토리를 마운트함
  • 파드를 재시작하더라도 호스트에 데이터가 남아있음
  • 호스트의 중요 디렉토리를 컨테이너에 마운트해서 사용할 수 있음
  • 쿠버네티스 클러스터 노드에 로그 파일을 저장하거나 CA 인증서 및 토큰을 파드에 제공하기 위한 용도로 사용 가능
  • 도커 시스템용 디렉토리를 컨테이너에서 사용할 때나 시스템용 디렉토리를 마운트해서 시스템을 모니터링하는 용도로 사용 가능

 


 

hostPath 실습

사전 작업

  • kube-node1 노드에 접속
  • /web_contents 디렉토리 생성
  • 디렉토리 안에 index.html 파일 생성
vagrant@kube-master1:~$ ssh vagrant@192.168.56.21

vagrant@kube-node1:~$ sudo mkdir /web_contents

vagrant@kube-node1:~$ echo "hello hostPath Volumes" | sudo tee /web_contents/index.html
hello hostPath Volumes

 

hostPath 구성

  • 레플리카셋 생성 파일
  • 1. .spec.containers[].volumeMounts: 볼륨 마운트 설정
  • .name: web-content 볼륨 이름 지정
  • .mountPath: 볼륨을 컨테이너의 /usr/share/nginx/html 디렉토리에 마운트하도록 설정
  • 2. .spec.volumes: 볼륨 설정
  • .name: 볼륨 이름 설정
  • . type: 설정한 경로 타입
  • .hostPath.path: 호스트의 볼륨 디렉토리 설정
vagrant@kube-master1:~/hostPath$ cat myapp-rs-hp.yml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: myapp-rs-hp
spec:
  replicas: 2
  selector:
    matchLabels:
      app: myapp-rs-hp
  template:
    metadata:
      labels:
        app: myapp-rs-hp
    spec:

      containers:
      - name: web-server
        image: nginx:alpine
        volumeMounts:	#----------------------------1
        - name: web-content
          mountPath: /usr/share/nginx/html
        ports:
        - containerPort: 80
      volumes:	#----------------------------2
      - name: web-content
        hostPath:
          type: Directory
          path: /web_contents

 

  • 서비스 생성 파일
vagrant@kube-master1:~/hostPath$ cat myapp-svc-hp.yml
apiVersion: v1
kind: Service
metadata:
  name: myapp-svc-hp
spec:
  type: LoadBalancer
  ports:
  - port: 80
    targetPort: 80
  selector:
    app: myapp-rs-hp

 

  • 레플리카셋, 서비스 생성
vagrant@kube-master1:~/hostPath$ kubectl create -f myapp-rs-hp.yml -f myapp-svc-hp.yml
replicaset.apps/myapp-rs-hp created
service/myapp-svc-hp created

 

실행 결과

  • myapp-rs-hp 파드 2개 생성
  • myapp-rs-hp 레플리카셋 생성
  • myapp-svc-hp 로드밸런서 생성
  • 오류 발생: 한 개의 파드가 제대로 실행되지 않음 (CotainerCreating 상태가 지속됨)
vagrant@kube-master1:~/hostPath$ kubectl get all
NAME                         READY   STATUS              RESTARTS   AGE
pod/myapp-rs-hp-6bcn8        0/1     ContainerCreating   0          10s
pod/myapp-rs-hp-thfgp        1/1     Running             0          10s

NAME                        TYPE           CLUSTER-IP      EXTERNAL-IP      PORT(S)        AGE
service/myapp-svc-hp        LoadBalancer   10.233.46.71    192.168.56.201   80:31404/TCP   10s

NAME                               DESIRED   CURRENT   READY   AGE
replicaset.apps/myapp-rs-hp        2         2         1       10s

 

  • 실행되지 않는 파드의 이벤트 확인
  • 볼륨 마운트에 실패함
vagrant@kube-master1:~/hostPath$ kubectl describe pods myapp-rs-hp-6bcn8
Events:
  Type     Reason       Age                   From               Message
  ----     ------       ----                  ----               -------
  Normal   Scheduled    8m46s                 default-scheduler  Successfully assigned default/myapp-rs-hp-6bcn8 to kube-node2
  Warning  FailedMount  4m26s                 kubelet            Unable to attach or mount volumes: unmounted volumes=[web-content], unattached volumes=[default-token-wl2vl web-content]: timed out waiting for the condition
  Warning  FailedMount  2m8s (x2 over 6m44s)  kubelet            Unable to attach or mount volumes: unmounted volumes=[web-content], unattached volumes=[web-content default-token-wl2vl]: timed out waiting for the condition
  Warning  FailedMount  33s (x12 over 8m47s)  kubelet            MountVolume.SetUp failed for volume "web-content" : hostPath type check failed: /web_contents is not a directory

 

  • 실행되고 있는 파드의 이벤트 확인
  • 마운트에 실패한 파드의 이벤트와 비교
vagrant@kube-master1:~/hostPath$ kubectl describe pods myapp-rs-hp-thfgp
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  11m   default-scheduler  Successfully assigned default/myapp-rs-hp-thfgp to kube-node1
  Normal  Pulling    11m   kubelet            Pulling image "nginx:alpine"
  Normal  Pulled     10m   kubelet            Successfully pulled image "nginx:alpine"
  Normal  Created    10m   kubelet            Created container web-server
  Normal  Started    10m   kubelet            Started container web-server

 

  • 파드가 생성된 노드의 위치 확인
  • 정상 실행 중인 파드는 kube-node1에 생성됨
  • 마운트에 실패한 파드는 kube-node2에 생성된 것을 확인
  • kube-node2에 /web_contents 디렉토리가 존재하지 않아 마운트에 실패했다는 것을 알 수 있음
vagrant@kube-master1:~/hostPath$ kubectl get pods -o wide
NAME                     READY   STATUS              RESTARTS   AGE    IP              NODE         NOMINATED NODE   READINESS GATES
myapp-rs-hp-6bcn8        0/1     ContainerCreating   0          14m    <none>          kube-node2   <none>           <none>
myapp-rs-hp-thfgp        1/1     Running             0          14m    10.233.101.92   kube-node1   <none>           <none>

 

오류 해결

  • 파드를 kube-node1 노드에 생성하여 볼륨을 공유하도록 구성
  • 리플리카셋 생성 파일에서 파드를 생성할 노드 지정
  • .spec.template.spec.nodename=kube-node1 추가
vagrant@kube-master1:~/hostPath$ cat myapp-rs-hp.yml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: myapp-rs-hp
spec:
  replicas: 2
  selector:
    matchLabels:
      app: myapp-rs-hp
  template:
    metadata:
      labels:
        app: myapp-rs-hp
    spec:
      nodeName: kube-node1	# 추가
      containers:
      - name: web-server
        image: nginx:alpine
        volumeMounts:
        - name: web-content
          mountPath: /usr/share/nginx/html
        ports:
        - containerPort: 80
      volumes:
      - name: web-content
        hostPath:
          type: Directory
          path: /web_contents

 

  • 레플리카셋 삭제 후 다시 생성
vagrant@kube-master1:~/hostPath$ kubectl delete -f myapp-rs-hp.yml
replicaset.apps "myapp-rs-hp" deleted

vagrant@kube-master1:~/hostPath$ kubectl create -f myapp-rs-hp.yml
replicaset.apps/myapp-rs-hp created

 

  • 생성된 파드 정보 확인
  • 두 개의 파드 모두 kube-node1 노드에 생성되어 정상 실행되고 있음
vagrant@kube-master1:~/hostPath$ kubectl get svc,pods -o wide
NAME                        TYPE           CLUSTER-IP      EXTERNAL-IP      PORT(S)        AGE     SELECTOR
service/myapp-svc-hp        LoadBalancer   10.233.46.71    192.168.56.201   80:31404/TCP   23m     app=myapp-rs-hp

NAME                         READY   STATUS    RESTARTS   AGE     IP              NODE         NOMINATED NODE   READINESS GATES
pod/myapp-rs-hp-lpfq6        1/1     Running   0          2m36s   10.233.101.93   kube-node1   <none>           <none>
pod/myapp-rs-hp-vg98c        1/1     Running   0          2m36s   10.233.101.94   kube-node1   <none>           <none>

 

  • 각 파드에서 동일한 볼륨에 마운트되었는지 확인
vagrant@kube-master1:~/hostPath$ kubectl exec myapp-rs-hp-lpfq6 -- cat /usr/share/nginx/html/index.html
hello hostPath Volumes

vagrant@kube-master1:~/hostPath$ kubectl exec myapp-rs-hp-vg98c -- cat /usr/share/nginx/html/index.html
hello hostPath Volumes

# 로드밸런서 연결 확인
vagrant@kube-master1:~/hostPath$ kubectl run nettool -it --image=c1t1d0s7/network-multitool --rm=true bash
If you don't see a command prompt, try pressing enter.
bash-5.0#
bash-5.0# curl http://myapp-svc-hp
hello hostPath Volumes
bash-5.0# curl http://10.233.46.71
hello hostPath Volumes
bash-5.0# curl http://192.168.56.201
hello hostPath Volumes
728x90

'쿠버네티스 교육 > 강의 내용 정리' 카테고리의 다른 글

220630_1_k8s_Secret  (0) 2022.06.30
220629_4_k8s_ConfigMap  (0) 2022.06.29
220628_3_k8s_볼륨_emptyDir  (0) 2022.06.28
220628_2_k8s_headless 서비스  (0) 2022.06.28
220628_1_k8s_프로브-readinessProbe  (0) 2022.06.28
728x90

emptyDir


emptyDir란?

임시로 데이터를 저장하는 빈 볼륨

  • 호스트의 디스크를 임시로 컨테이너에 볼륨으로 할당하여 사용
  •  하나의 노드 내에서 여러 파드가 emptyDir를 공유할 수 있음
  • 동일한 파드 내에서 컨테이너 간에 데이터를 공유할 때 유용함
  • 컨테이너에 문제가 발생하여 재시작되더라도 파드는 살아있으므로 emptyDir에 저장해둔 데이터는 계속 사용 가능함
  • 파드가 사라지면 emptyDir에 할당해서 사용했던 볼륨의 데이터도 함께 사라짐

 

특징

  • 볼륨이지만 데이터를 영구 저장하지 않음
  • 파드의 라이프사이클과 동일함
  • 간편하게 설정 가능
  • 디스크 / 메모리를 이용함

 

 


 

실습

두 개의 컨테이너가 하나의 볼륨을 공유하여 사용

  • 레플리카셋 생성 파일
  • 하나의 파드에 두 개의 컨테이너 생성( web-server / html-fortune )
  • 1. .spec.template.spec.volumes: 사용하려는 볼륨 선언
  • - .name: 볼륨 이름 지정
  • - .emptyDir: emptyDir 사용을 위해 빈 값( {} )으로 설정
  • 2. .spec.template.spec.containers.volumeMounts: 마운트할 볼륨 지정
  • - .name: 마운트할 볼륨 이름
  • - .mountPath: 마운트포인트
$ cat myapp-rs-emptydir.yml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: myapp-rs-fortune
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myapp-rs-fortune
  template:
    metadata:
      labels:
        app: myapp-rs-fortune
    spec:
      containers:
      - name: web-server
        image: nginx:alpine
        volumeMounts:	#-----------------------2
        - name: web-fortune
          mountPath: /usr/share/nginx/html
          readOnly: true
        ports:
        - containerPort: 80
      - name: html-generator
        image: ghcr.io/c1t1d0s7/fortune
        volumeMounts:	#-----------------------2
        - name: web-fortune
          mountPath: /var/htdocs
      volumes:	#-----------------------1
      - name: web-fortune
        emptyDir: {}

 

  • 로드밸런서 서비스 생성 파일
$ cat myapp-svc-emptydir.yml
apiVersion: v1
kind: Service
metadata:
  name: myapp-svc-fortune
spec:
  type: LoadBalancer
  ports:
  - port: 80
    targetPort: 80
  selector:
    app: myapp-rs-fortune

 

  • 레플리카셋, 서비스 생성
$ kubectl create -f myapp-rs-emptydir.yml -f myapp-svc-emptydir.yml
replicaset.apps/myapp-rs-fortune created
service/myapp-svc-fortune created

 

  • 컨테이너에 접속하여 볼륨 마운트가 제대로 되었는지 확인
  • web-fortune 볼륨에 마운트하여 정상 작동하는 것을 확인할 수 있음
$ kubectl exec myapp-rs-fortune-2tl24 -c web-server -- cat /usr/share/nginx/html/index.html

$ kubectl exec myapp-rs-fortune-2tl24 -c html-generator -- cat /var/htdocs/index.html

 

  • 별도의 파드를 생성하여 컨테이너들이 정상 작동하는지 확인
$ kubectl run nettool -it --image=c1t1d0s7/network-multitool --rm=true bash
If you don't see a command prompt, try pressing enter.
bash-5.0#
bash-5.0# curl http://myapp-svc-fortune
You will be run over by a bus.

 

728x90
728x90

headless service


헤드리스 서비스란?

Cluster IP가 없는 서비스

  • 일반적으로 파드 그룹을 서비스의 엔드포인트에 등록하고, 로드밸런서를 사용함
  • 그러나, 로드밸런싱이나 단일 서비스 IP가 필요 없는 경우도 있음
  • 이 때, 사용하는 것이 headless service
  • .spec.clusterIP: None

 

selector가 있는 경우

  • 엔드포인트 컨트롤러는 API에서 엔드포인트 레코드를 생성하고,
  • DNS 구성을 수정하여  서비스를 지원하는 파드를 직접 가르키는 A 레코드를 반환함

 

selector가 없는 경우

  • 엔드포인트 컨트롤러는 엔드포인트 레코드를 생성하지 않음
  • DNS 시스템은 ExternalName 타입의 서비스에서 사용할 CNAME 레코드가 생성됨

 


 

실습

Cluster IP가 없지만 엔드포인트에 등록된 파드의 정보와 A 레코드 확인

  • 레플리카셋 생성 파일
$ cat myapp-rs-headless.yml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: myapp-rs-headless
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp-rs-headless
  template:
    metadata:
      labels:
        app: myapp-rs-headless
    spec:
      containers:
      - name: myapp
        image: ghcr.io/c1t1d0s7/go-myweb:alpine
        ports:
        - containerPort: 8080

 

  • 헤드리스 서비스 생성 파일
$ cat myapp-svc-headless.yml
apiVersion: v1
kind: Service
metadata:
  name: myapp-svc-headless
spec:
  clusterIP: None
  ports:
  - port: 80
    targetPort: 8080
  selector:
    app: myapp-rs-headless

 

  • 파드, 서비스 생성
$ kubectl create -f myapp-rs-headless.yml -f myapp-svc-headless.yml
replicaset.apps/myapp-rs-headless created
service/myapp-svc-headless created

 

실행 결과

  • 생성된 파드, 엔드포인트, 서비스 정보 확인
  • headless 서비스의 엔드포인트에 파드들의 IP가 등록되어 있음
  • CLUSTER-IP는 None으로 IP가 지정되지 않음
$ kubectl get po,ep,svc -o wide

 

  • DNS A 레코드 확인을 위해 파드 실행
$ kubectl run nettool -it --image=c1t1d0s7/network-multitool --rm=true bash

 

  • nslookup
bash-5.0# nslookup myapp-svc-headless
Server:         169.254.25.10
Address:        169.254.25.10#53

Name:   myapp-svc-headless.default.svc.cluster.local
Address: 10.233.101.103
Name:   myapp-svc-headless.default.svc.cluster.local
Address: 10.233.76.148
Name:   myapp-svc-headless.default.svc.cluster.local
Address: 10.233.103.76

 

  • host
bash-5.0# host myapp-svc-headless
myapp-svc-headless.default.svc.cluster.local has address 10.233.101.103
myapp-svc-headless.default.svc.cluster.local has address 10.233.76.148
myapp-svc-headless.default.svc.cluster.local has address 10.233.103.76

 

  • dig
  • ANSWER SECTION 항목에서 A 레코드를 확인할 수 있음
bash-5.0# dig myapp-svc-headless.default.svc.cluster.local

~
;; ANSWER SECTION:
myapp-svc-headless.default.svc.cluster.local. 5 IN A 10.233.101.103
myapp-svc-headless.default.svc.cluster.local. 5 IN A 10.233.103.76
myapp-svc-headless.default.svc.cluster.local. 5 IN A 10.233.76.148
~
728x90

+ Recent posts